Giter Site home page Giter Site logo

gdquest / godot-steering-ai-framework Goto Github PK

View Code? Open in Web Editor NEW
1.0K 37.0 77.0 827 KB

A complete framework for Godot to create beautiful and complex AI motion. Works both in 2D and in 3D.

Home Page: http://gdquest.com/docs/godot-steering-ai-framework

License: MIT License

GDScript 100.00%
godot ai artificial-intelligence steering-behaviors game-development agents gdscript algorithms framework godot-game-engine

godot-steering-ai-framework's Introduction

Godot Steering AI Framework

Project banner

This project is a framework to code complex and smooth AI movement in the Godot game engine, in GDScript, using steering behaviors. It works in both 2D and 3D games.

โžก Follow us on Twitter and YouTube for free game creation tutorials, tips, and news! Get one of our Godot game creation courses to support our work on Free Software.

It supports all essential steering behaviors like flee, follow, look at, but also blended behaviors, group behaviors, avoiding neighbors, following a path, following the leader, and much more.

Getting the framework

This repository contains the framework and some demos for learning purposes.

If you want just the framework with nothing else to get in the way or to create a Git submodule, use the Godot Steering AI Framework Submodules repository.

Introduction

In the 1990s, Craig Reynolds developed algorithms for common AI behaviors. They allowed AI agents to seek out or flee from a target, follow a pre-defined path, or face in a particular direction. They were simple, repeatable tasks that could be broken down into programming algorithms, which made them easy to reuse, maintain, combine, and extend.

While an AI agent's next action is based on decision making and planning algorithms, steering behaviors dictate how it will move from one frame to the next. They use available information and calculate where to move at that moment.

Joining these systems together can give sophisticated and graceful movement while also being more efficient than complex pathfinding algorithms like A*.

The framework

This project is a framework for the Godot game engine. It takes inspiration from the excellent GDX-AI framework for the LibGDX java-based framework.

Every class in the framework extends Godot's Reference type. There is no need to have a complex scene tree; you can contain that has to do with the AI's movement inside GDScript classes.

How it works

In GSAI, a steering agent represents a character or a vehicle. The agent stores its position, orientation, maximum speeds, and current velocity. The agent stores a steering behavior that calculates a linear or angular change in velocity based on its information.

The coder then applies that acceleration in whatever ways is appropriate to the character to change its velocities, like RigidBody's apply_impulse, or a KinematicBody's move_and_slide.

Documentation

The framework's documentation and code reference are available here: Godot steering AI framework documentation

Contributing

If you encounter a bug or you have an idea to improve the tool, please open an issue.

If you want to contribute to the project, for instance by fixing a bug or adding a feature, check out our:

  1. Contributor's guidelines.
  2. GDScript style guide

Support us

Our work on Free Software is sponsored by our Godot game creation courses. Consider getting one to support us!

If you like our work, please star the repository! This helps more people find it.

Join the community

  • You can join the GDQuest community and come chat with us on Discord
  • For quick news, follow us on Twitter
  • We release video tutorials and major updates on YouTube

godot-steering-ai-framework's People

Contributors

codedoes avatar daneehai avatar feois avatar jantho1990 avatar nathanlovato avatar razoric480 avatar volzhs 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  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  avatar  avatar  avatar  avatar  avatar

godot-steering-ai-framework's Issues

Auto-calculate deceleration radius in behaviors

Add a flag to have the ability to have the behaviors calculate the deceleration radius automatically for behaviors that use them, when exact-arrival is desired.

However, keeping it able to be set manually would keep flexibility up, in case someone wants an agent that slows down gradually from a longer distance than what the math would call for.

The arrive demo's UI doesn't scale

This is because the demo has a Node2D as its root node. It needs refactoring to move the drawing code away from the scene's root node.

Add additional behaviors

There are more behaviors out there and they could prove useful for certain games. They should be their own issues, but they are gathered here for discussion and as a central location for now.

Some contenders:

Individual

  • Wander: Gives an agent an acceleration in a random direction inside of its environment.
  • RaycastObstacleAvoid: Uses raycasts to give an agent an angular acceleration that will keep it from running into obstacles
  • FollowFlowField: Gives an agent an acceleration along the tangent of a flowfield's direction vectors or a heatmap's numerical difference.
  • Interpose: Gives an agent an acceleration that will take it to a target but through an imaginary line between two other agents.
  • Jump: Gives an acceleration that will take it to a starting point with enough speed to commit to a jump and reach a target destination upon landing, using a callback or signal.

Group

  • Alignment: Gives an agent an angular acceleration to rotate and face the same direction as everyone in its proximity
  • Hide: Gives an agent an acceleration that will move it to a position where an obstacle in its proximity is between it and its target
  • Follow the leader: Gives an agent an acceleration that will move it into position to follow a given leader in its proximity
  • Queue: Gives an agent an acceleration that will move it through a target point without conflicting with others in its proximity trying to do the same.

The flee demo's bounds aren't drawn in the correct location

I moved the collision boxes in the last commit, but the areas' drawing code doesn't take the boxes' position into account.

I'd recommend refactoring the code so there's only one area that draws the 4 rectangles

for i in get_children():
    draw_rectangle...

FollowPath: the agent does not always manage to follow the path

Depending on the location and the shape of the path the user draws, the agent can loop over the path:

  • It moves along the path to one end
  • And then loops back to the other end

Also, when the path makes a sharp turn, e.g. when you have a portion with a V shape, the agent doesn't manage to follow the path.

Memory leak upon exiting Godot

This is an issue with Godot's type system, in some cases, types can cause memory leaks.

Running Godot with the verbose option:

Leaked instance: GDScriptNativeClass:555
Leaked instance: GDScript:18650 - Resource name:  Path: res://src/GSAITargetAcceleration.gd

This happens when types reference themselves. We had that in Mannequiny: gdquest-demos/godot-3d-mannequin#30

GSAIKinematicBody agents continue processing when outside of the scene tree

I'm submitting a...

  • Bug report.
  • Feature request.

Bug report

What is the current behavior?
When GSAIKinematicBody2DAgent is outside of the main scene tree, it continues to try and update itself. Since it is not in the scene tree, this results in calls to global_position returning the local transform instead of the global transform, and this messes up velocity calculations when the agent is reinserted into the scene tree.

Observed this with the 2D agent, but the bug would be present for a 3D agent as well (both Kinematic and Rigid).

What is the expected behavior?
Agents should not try to update themselves if they are outside of the scene tree.

Tell us the steps to reproduce the bug, and if possible share a minimal demo of the problem.
Create three scenes: one scene containing a GSAIKinematicBody2DAgent, one without the agent, and a third scene that toggles which of the previous two scenes is currently loaded. Start the game with the scene containing the agent and observe it trying to move; then switch to the scene without the agent; then switch back.

You should observe the agent starts from zero velocity; this is due to having used local transforms to try and calculate its velocity, resulting in reducing the internal velocity to zero.

Other

I already know how to fix this bug, just reporting this as an issue for documentation's sake before I pull the repo locally to make the fix.

API reference writing and maintenance

This issue focuses on the need to have a way to create documentation for API, class-sets and other code-centric assets.

Ideally we could come up with something that works as nice as Godot's references, or Stripes' (probably Godot's since GDQuest's docs system works on the same one Godot uses.)

GDScript currently lacks a way to extract docstrings to create a documentation easily, unlike a tool like JavaDoc, doxygen, or Sphinx. So we would either need to either create a tool, tie into another, or extract the code into a JSON dump for documentation.

Nathan's comments on the matter, just to get the conversation resumed:

Thanks! I wish GDScript had something like Python, where we can extract docstrings.

When it comes to writing the API, I'd follow the guidelines from another project or company that has great API ref. We can follow the ones from Godot.

Also, I'd write a tool to make it easier to document our APIs, but that may require us to have a programming guideline to differentiate private and virtual functions. So, we'd probably need to use two leading underscores for private stuff, as in Python.

How about the place to write the reference? I'd like to have the equivalent of Python's docstrings in the source code. That way, any dev or user contributing a change will know where to update the function description. A script could then extract these docstrings. There's a problem with that though, it makes the code full of comments and a bit cumbersome to update:

# Caps the agent's movement speed.
var speed_max := 0.0
# Controls the inertia of the agent.
var drag := 1.0

Thinking about it though, creating a tool should mean that for compatibility, the API shouldn't change that much once we release the first version. Closed to modification, opened to extension, right.

It's just a pity that, unlike in Python, we don't have a built-in mechanism in GDScript to document the code.

The other efficient option is to have a tool like in the Godot repository, that collects all the functions and dumps them to a JSON file, in which we then write the docs. I could use https://github.com/Scony/godot-gdscript-toolkit to make that quickly, it features a GDScript parser.

In either case, we can have an extensible JSON file to generate the docs from, with fields like:

  • description, possibly the docstring extracted from the source code
  • example, a code example in gdscript
  • tags, possibly extracted from the source code

What do you think?

Worth pointing out that whatever we go with is likely to be carried over into other projects. The toolkit just happens to be the first main API we've got going.

Bring Separation and Cohesion into similar math

Currently, putting equal parts Cohesion and Separation leads to math that vastly favours Cohesion, and requires Separation be given a decay_coefficient in the hundreds of thousands to millions range, and to give it a blended strength that is an order of magnitude stronger than the Cohesion.

Putting a 1:1 ratio of the two behaviors should cause close-to-zero amounts of acceleration, after an adjustment period, without large amounts of tweaking.

Though it should be done in a way that does not compromise the difference between Separation and Cohesion:

  • Cohesion should still be a behavior that tries to move towards the proximity's center of mass
  • Separation should still be a behavior that tries to move away from other units in the proximity, with closer units causing higher values.

Add 3D demo

While the 2D side of the framework has been pretty thoroughly tested both before and during its development, its 3D has been built largely on assumptions.

3D demos would let tests be run while also giving users a chance to learn how to make the most of it in 3D.

Add specalized agents

Specialized agents would be steering agents that are specialized towards RigidBody/2D, KinematicBody/2D, and Spatial/Node2D. They update themselves every frame, have a "current_behavior" property, and a virtual "_apply_steering" method that applies that behavior.

For simple cases, this can often be all you really need. For more specialized cases, the player can roll their own or extend these.

Looking to contribute: I am basically finished porting this repo to Godot 4.1.1

Hi!

As the title says, I ported this repo to Godot 4.1.1.

There don't seem to be any unit tests etc; but the code conversion was mostly a matter of swapping out deprecated datatypes for new ones and updating the syntax here and there.

The Arrive3d demo scene required some tinkering with rotations and shape parameters as well as lighting to make it look like the Godot 3 version as closely as possible.

Scaling of 2D scenes is still a bit broken, but I think I'll be able to fix that tomorrow.

Please let me know how to proceed after that! Do I just make a pull request that a GDQuest team member then checks?

Kind regards,
Dani

Collision detection in groups leads to jiggly movement

From @jknightdoeswork:

Im struggling to avoid having groups "jiggle" when they have no input, but still avoid collisions nicely when moving at speed. I'm lerping the avoidance radius to help with this.

From @Razoric480

This might be an issue exclusive to having lots of agents running avoid collision. I do notice some jiggling in the avoid collision demo just because of how the avoid collision behavior works. Which is pick the nearest obstacle and move away from it. If that nearest obstacle keeps changing, it'll jiggle.

Create a game that showcases the toolkit

Harvester

Harvester is a top down space mining game. Control your spaceship in forays into an asteroid belt, gather resources, and bring them back to base. Spend them to upgrade your ship's speed and manoeuvrability, cargo space, tools, and build automated helper drones.

Beware, however; you are not alone out here. Pirate miners and native space-life stake out territories and take umbrage with your operation.

Summary

The player begins with a simple ship at their space station in a relatively large, procedurally generated map filled with asteroids, resources and debris. Their job is to navigate their way to find, map out, and collect resources and take them back to the station.

As they accumulate resources and score, enemy pirates and native space wildlife begin to spawn and stake out their own territories around veins. This forces the player to take different paths until they are able to devise ways to distract or destroy the interlopers.

The player continues until they are overwhelmed by the mounting difficulty and growing opposition and sees how far they can go.

Development

The game is meant to showcase the GDQuest Godot Steering Toolkit while still being a fun time waster. As a result, the two different enemy factions and the automated drones will demonstrate very different behaviors built with the toolkit:

  • The wildlife will seek you out rather simply, aiming to attach itself to your ship until scared off. They can also chase after pirate ships.
  • The pirate faction will intercept you more intelligently, getting you within range of their weapons but keeping a safe distance while avoiding asteroids and debris. They are also more likely to work in groups, and will seek out mineral veins to take to their own base until you get too close.
  • The drones will move from the base to the resource veins simply and efficiently, following the path you laid out for them while avoiding collisions with asteroids.
  • The player, to repair/refuel/deposit cargo or to mine, will use an AI assisted docking mechanism.

This baseline summary of the behaviors could change based on player upgrades and special tools that are unlocked. This offers a nice variety of in-context behaviors while keeping those behaviors simply coded.

The game has a relatively simple base, with the main mechanic being a top-down spaceship that dodges and mines. But the brunt of the extra features would be progression and unlockables, which makes it a game that can be revisited and added to without unnecessary refactoring.

Pre-rendered 3D sprites will be the main graphic. I've been away from making art for a while and would like to get my fingers dipped in once again.

Improve structure of the repositories

We updated this repo lately to make it easier to add the framework to your own games. The demos are now a separate project, https://github.com/GDQuest/godot-steering-ai-framework-demos

But:

  • It's not convenient yet to clone this repository as a submodule, it comes with some useless files.
  • Demos are hard to find.

We should clearly and prominently cross-link the two repositories, but also find a way to make installing the framework as efficient as possible.

@Razoric480 How about having this repo as the main one with demos, so people can test, and having a bare repository that's just for submodules instead? The idea of this main repo, that's the most starred, is to help people discover and get started with the framework. So having the demos would be welcome I think.

I also don't like too much that we'd have to maintain two repos and copy the framework to the second repo to do that. Not sure there's a way around that though.

GSAIKinematicBody agents continue processing when the scene tree is paused

I'm submitting a...

  • Bug report.
  • Feature request.

Bug report

What is the current behavior?
When the scene tree is paused, agents continue to update themselves, resulting in their velocity zeroing out.

What is the expected behavior?
Agents should not update themselves if the scene tree they belong to is paused.

Tell us the steps to reproduce the bug, and if possible share a minimal demo of the problem.
Create a scene with a GSAIKinematicBody2DAgent, then write a script that allows you to toggle pausing and unpausing the scene tree.

Each time the game pauses and unpauses, you should observe the agent starts from zero velocity; this is due to having used local transforms to try and calculate its velocity, resulting in reducing the internal velocity to zero.

Other

Other information
This is exactly the same issue as #54, but with pausing the scene tree instead of having objects outside of the scene tree.

I'll get a PR for this issue up shortly.

Write the getting started documentation

The quick-start documentation and user's guide needs to be written up to reach the MVP stage. The docstring for the classes could also use some improvement.

Rename classes to GSAI*

Rename the classes to match the new project name, and bump up the version. It was still freshly released so I think we'd better rename early and write a note for people to search and replace GST with GSAI in their code.

Also add a short note for users to search and replace when they upgrade to 1.1.

Body variable is not set in GSAIRigidBody2DAgent

I'm submitting a...

  • Bug report.
  • Feature request.

Bug report

What is the current behavior?
Body variable is not set in GSAIRigidBody2DAgent, so it crashes

What is the expected behavior?
Body variable should be set in _init method

Visual scripting

I'm submitting a...

  • Bug report.
  • Feature request.

Feature request

Describe the problem you're trying to solve.
I'd like to use this library with Visual Script

Tell us which solutions you've explored, the solution you would pick, and why you think it would be the best for everyone.
None yet

Other

Other information
none

GSAIKinematicBody3DAgent.gd uses KinematicBody.global_position which does not exist

I'm submitting a...

  • Bug report.
  • Feature request.

Bug report

What is the current behavior?
GSAIKinematicBody3DAgent uses global_position which exists in 2d but not in 3d

What is the expected behavior?

Tell us the steps to reproduce the bug, and if possible share a minimal demo of the problem.

Feature request

Describe the problem you're trying to solve.

Tell us which solutions you've explored, the solution you would pick, and why you think it would be the best for everyone.

Other

Other information

calculate_velocities inverts velocity direction

GSAIUtils.to_vector3(_last_position - current_position), linear_speed_max

Hi
I have an agent (the enemy) pursuing the player , when the distance is under a certain threshold
the enemy should stop and then dash the player.
I noticed that when the enemy has to stop it suddenly flips the velocity's direction.
Note: the enemy code didn't apply a behaviour for a frame (so the velocity is calculated by the formula)
I think there is an error in the formula to calculate the velocity of the agent if no behaviour was applied in the last frame. Shouldn't it be current_pos - last_pos ?

the library is wonderful and very useful thanks! <3

Outdated Documentation

The documentation for the Installation and Getting Started pages is outdated.

Installation
https://www.gdquest.com/docs/godot-steering-ai-framework/how-to-install/

  1. Copy the content of the project/src/ directory

This path is not in the 3.0.0 release of the library. The current path seems to be addons/com.gdquest.godot-steering-ai-framework/.

Getting Started
https://www.gdquest.com/docs/godot-steering-ai-framework/getting-started/

You can see the demo in action by running the demos/QuickStartDemo.tscn scene in Godot.

There is no longer a demos folder or any demo .tscn files in the 3.0.0 release.

Rustlang and C# implemtation

I'm submitting a...
I am submitting a sudjection to make a nuget package and a rust crate for this framework, I am prepard to port the who code base myselft, and submitt a pull request

  • Bug report.
  • Feature request.

Bug report

What is the current behavior?

What is the expected behavior?

Tell us the steps to reproduce the bug, and if possible share a minimal demo of the problem.

Feature request

Describe the problem you're trying to solve.

Tell us which solutions you've explored, the solution you would pick, and why you think it would be the best for everyone.

Other

Other information

Expand framework for 3D agents to rotate on more than one axis

To simplify the math, the base behaviors currently only operate on one axis as far as their rotation and orientation goes; pretty much implying them to be 2D agents in a 3D world.

They can move in all axis, but rotation is locked to Y axis. It's fine for most games where agents will be upright beings and cars, but falls short for six-axis games.

Special orientation behaviors can be introduced that work on multiple axis. It would necessitate extending TargetAcceleration to support Quat/Basis and extending the 3D Kinematic/Rigid agents to override their _apply_orientation methods (as well as adding a GSAIMatchOrientation3D, Face3D and LookWhereYouGo3D.)

Missing installation Instructions

I'm submitting a...

  • Bug report.
  • [x ] Feature request.

Feature request

Describe the problem you're trying to solve.
There is no installation instructions. Although the code examples are nicely laid, out, how to get the framework into your codebase to carry out the examples is not specified.

I was looking for installation instructions without having to look at the project structure.
Tell us which solutions you've explored, the solution you would pick, and why you think it would be the best for everyone.
I believe it would be best to update the README and the documentation.

Automatically build a GUI by looking at the exported variables and their types

While the Demo Selector is useful, one downside is that you can't change values quite as easily; needing to go into the Remote Tree to do so. So it's nice for showcase, but for actual study and playing around with the variables, opening the actual demo will still be called for.

Occasionally, Godot's keep-window-on-top option also stops working for unexplained reasons, depending on the state of your alt-tabbing and clicking, so using the inspector for all tweaking starts to lose some of its lustre.

An in-demo GUI system that we don't have to manually build but that automatically outputs the exported variables that are on the root node would alleviate all of those issues.

Add a main scene that allows you to run all the demos?

Considering we have demos, how about having a default scene that:

  1. Opens with the project, instead of leaving you on a blank viewport.
  2. Runs when pressing F5.
  3. Allows you to cycle through the demos, loading them on the fly.

It should probably auto-discover the demos too, easy enough by finding all files that are named *demo*.tscn (case insensitive check). We can adapt the code from Collector.gd to do just that.

Extend GSTUtils

  • Vector2 <=> Vector3 conversion and vice versa
  • Vector2 to Vector3 multiplication, addition, subtraction and division and vice versa

Finish the remaining toy demos

There are a few demos that still need to be finished to reach MVP stage. Those are:

  • Path Following toy demo
  • Avoid Collisions toy demo
  • A global, game-like demo to show them in context

Elements common to each demo should also be split into common classes - such as a 2D steerable agent. This will make the demos a little easier to maintain.

Add debug visualizer

A special Node2D/Spatial/PackedScene that can be added to a scene and fed an agent and/or behavior, with the ability to draw whatever information is relevant or selected by the programmer.

  • Arrows for directions
  • Lines for raycasts
  • PolyLines for paths
  • Circles for predicted target positions
  • Numerical data, like current velocities and accelerations

Add parallelism for proximity behaviors

The current implementation of the proximity behaviors involves iterating over anyone who "fits the bill" of the proximity and then calling a callback on them to act upon the behavior as necessary.

Once it's out of the proximity's hands, the potential for a worker thread or two or more to substantially increase performance is significant, especially when there are a lot of agents.

Planning the first version: minimum viable product

The readme is still a little technical and outlines many features the framework could have.

To get started, we need to ensure that there are enough developers who want this tool to support its development. And to convince people that it's useful, we're going to create a minimum viable product.

This first milestone is the smallest package we can have that contains the essentials to start solving concrete problems Godot users, developers and designers alike, have.

To help us figure that out, I'd need:

  1. A short list of the most important general game design problems the framework can solve. A non-exhaustive ordered list, from the most to the least common problem.
    • This list will help set our focus, help us scope each version, and stay focused on solving problems that people actually have. Otherwise, we may end up with features that nobody will use.
    • It's also a list to help explain why this framework is useful to the game designers or developers, especially for people who have little exp with AI or have never heard of steering behaviors before.
  2. A proposal for a minimum viable product. What's the subset of features we need for a usable v0.1 that'll help people already? Everything that's not absolutely essential or really common should be counted out of this proposal. A [nested] list of feature names without description is enough for me.

Add Link to Demos Repo in readme file

**I'm submitting a request to add a link to the Godot Steering AI Framework Demos repo to the Godot Steering AI Framework readme file. **

  • Bug report.
  • Feature request.

Bug report

What is the current behavior?

What is the expected behavior?

Tell us the steps to reproduce the bug, and if possible share a minimal demo of the problem.

Feature request

I currently have this bookmarked, but I can see new users having trouble finding the examples.

See above. If there is a link and I'm missing it, please let me know.

Other

Other information

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.