Skip to content

Commit

Permalink
✨ Add an example using the cute framework
Browse files Browse the repository at this point in the history
This shows off the very basic requirements of what's needed to embed a Dart as a game scripting language
  • Loading branch information
fuzzybinary committed Nov 9, 2023
1 parent 9c23bd4 commit fa78740
Show file tree
Hide file tree
Showing 12 changed files with 404 additions and 32 deletions.
58 changes: 27 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,46 @@ Additionally we may have a static target that uses the same interface as the dyn

I also hope to support all platforms that Dart currently supports, plus a few extra.

## Current Progress

A very, very simple Dart script works.

## Using

`TODO:`
Lastest builds of the libraries are now available for certain targets as artifacts from [Github Actions](https://github.com/fuzzybinary/dart_shared_libray/actions) as well as all the headers necessary.

Github Actions currently builds a Windows x64 `.dll`, A Linux x64 `.so`, and a macOS x64 `.dylib`. You can build a M-series dylib for macOS, but Github Actions does not currently support it.

## Building

### Prerequisets
You need
You need:
* git
* All the things to get Dart source - https://github.com/dart-lang/sdk/wiki/Building#source
* Dart 3+
* C++ build tools for your platform (Visual Studio, XCode, gcc, etc)
* CMake

## Contributing
Optionally, I recommend installing [`depot_tools`](https://www.chromium.org/developers/how-tos/depottools/) and making sure it is on your path before running setup scripts. Without depot_tools, the scripts will download them anyway, but having them already set up will save you some time with subsequent builds.

`TODO:`
### Patching and Building Dart

# What I Did
> NOTE: If you are building on Windows, I recommend running `.\setup_env.ps1` before executing any other scripts.
> This will set up some environment variables that will be needed to build Dart properly.
This section is as much for my benefit as for yours. Eventually, I hope to make a script that will do most of this.
The first step is to build a statically linkable verison of Dart. This requires that we download Dart, patch some of the Dart build files, and then run the actual build. Thankfully there is a Dart script to do this.

* Modify the BUILD.gn files to add a `libdart` target. This is done by applying the patch in `./dart_sdk.patch`
* Make sure all correct environment variables are set
* On Windows, these are set with the `setup_env.ps1` script. Specifically, you need to set `GYP_MSVS_OVERRIDE_PATH`, `GYP_MSVS_VERSION`, and `DEPOT_TOOLS_WIN_TOOLCHAIN=0`
* Builds libdart with:
```bash
# On windows, you will need to add `python` in front
./tools/build.py --no-goma -m release libdart
```
* Revert the changes made to build files to leave a clean copy of the dart-sdk (this makes updating easier)
* Build with CMake:
```
cmake -B ./.build .
cmake --build ./.build
```bash
dart ./scripts/build_helpers/bin/build_dart.dart
```

Updating the dart-sdk
* Make sure environment variables are set (`setup_env.ps1`)
* From `dart-sdk/sdk`:
* `git checkout tags/[version]`
* `gclient sync -D`
* reapply dart_sdk.patch (`git apply ../../dart_sdk.patch`)
* `python ./tools/build.py --no-goma -m release libdart`
This script does the following:
* Pulls down `depot_tools` if needed.
* Clones a fresh copy of the Dart sdk git repo using `fetch` if needed.
* Uses `gsync` to syncs the repo the the version of dart specificed in `.dart_version`.
* Applies `dart_sdk.patch` to the repo to create the statically linkable `libdart` library
* Builds `libdart`

### CMake

Once Dart is built, you can use CMake to generate build files and / or build the libraries and examples

```bash
cmake -B ./.build .
cmake --build .\.build\ --config release
```
3 changes: 2 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.21)

add_subdirectory(simple_example)
add_subdirectory(simple_example_ffi)
add_subdirectory(simple_example_ffi)
add_subdirectory(realtime_example)
2 changes: 2 additions & 0 deletions examples/realtime_example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.dart_tool/
pubspec.lock
39 changes: 39 additions & 0 deletions examples/realtime_example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.21)

project(realtime_example)
set(CMAKE_CXX_STANDARD 17)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

set(CUTE_FRAMEWORK_STATIC ON)

include(FetchContent)
FetchContent_Declare(
cute
GIT_REPOSITORY https://github.com/RandyGaul/cute_framework
)
FetchContent_MakeAvailable(cute)

add_executable(realtime_example
main.cpp
drawable.cpp
)

target_include_directories(realtime_example PRIVATE
"."
"${DART_DLL_DIR}"
"${DART_DIR}/runtime/include"
)

add_custom_target(ALWAYS_DO_POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy -t $<TARGET_FILE_DIR:realtime_example> $<TARGET_RUNTIME_DLLS:simple_example_ffi>
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/dart $<TARGET_FILE_DIR:realtime_example>/dart
COMMAND_EXPAND_LISTS
)
add_dependencies(realtime_example ALWAYS_DO_POST_BUILD)

target_link_libraries(realtime_example PUBLIC dart_dll cute)

if (MSVC)
set_property(TARGET realtime_example PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $<TARGET_FILE_DIR:realtime_example>)
endif()
14 changes: 14 additions & 0 deletions examples/realtime_example/dart/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Dart: Attach to Process",
"type": "dart",
"request": "attach",
"vmServiceUri": "http://127.0.0.1:5858/"
}
]
}
31 changes: 31 additions & 0 deletions examples/realtime_example/dart/drawable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'dart:ffi';

class CF_Color extends Struct {
@Float()
external double r;

@Float()
external double g;

@Float()
external double b;

@Float()
external double a;
}

class Drawable extends Struct {
@Int32()
external int x;

@Int32()
external int y;

@Int32()
external int width;

@Int32()
external int height;

external CF_Color color;
}
28 changes: 28 additions & 0 deletions examples/realtime_example/dart/ffi_calls.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'dart:ffi';

import 'drawable.dart';

class WorkFfiCalls {
final DynamicLibrary processLib = DynamicLibrary.process();

late final createEntity = processLib
.lookup<NativeFunction<Uint32 Function(Int32, Int32, Int32, Int32)>>(
'create_entity')
.asFunction<int Function(int, int, int, int)>(isLeaf: true);
late final destroyEntity = processLib
.lookup<NativeFunction<Void Function(Uint32)>>('destroy_entity')
.asFunction<void Function(int)>(isLeaf: true);
late final getDrawable = processLib
.lookup<NativeFunction<Pointer<Drawable> Function(Uint32)>>(
'get_drawable')
.asFunction<Pointer<Drawable> Function(int)>(isLeaf: true);

late final getKeyJustPressed = processLib
.lookup<NativeFunction<Bool Function(Uint32)>>('get_key_just_pressed')
.asFunction<bool Function(int)>(isLeaf: true);
}

const int CF_KEY_RIGHT = 145;
const int CF_KEY_LEFT = 146;
const int CF_KEY_DOWN = 147;
const int CF_KEY_UP = 148;
66 changes: 66 additions & 0 deletions examples/realtime_example/dart/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'dart:ffi';

import 'ffi_calls.dart';

WorkFfiCalls ffi = new WorkFfiCalls();

class Wall {
late int entity;

Wall(int x, int y, int width, int height) {
entity = ffi.createEntity(x, y, width, height);
final drawable = ffi.getDrawable(entity);
drawable.ref.color.r = 1.0;
drawable.ref.color.g = 0.0;
drawable.ref.color.b = 0.0;
drawable.ref.color.a = 1.0;
}
}

List<Wall> walls = [];

// Dot!
int dotEntity = 0;
int dotX = 0;
int dotY = 0;
bool movingLeft = true;

void main() {
print('main');
walls.add(
Wall(-320, -240, 5, 480),
);
walls.add(
Wall(315, -240, 5, 480),
);
walls.add(
Wall(-320, -240, 640, 5),
);
walls.add(
Wall(-320, 235, 640, 5),
);

dotEntity = ffi.createEntity(0, 0, 10, 10);
final drawable = ffi.getDrawable(dotEntity);
drawable.ref.color.g = 1.0;
}

void frame(double dt) {
if (movingLeft) {
dotX -= 3;
if (dotX < -200) {
dotX = -200;
movingLeft = false;
}
} else {
dotX += 3;
if (dotX > 200) {
dotX = 200;
movingLeft = true;
}
}

final dotDrawable = ffi.getDrawable(dotEntity);
dotDrawable.ref.x = dotX;
dotDrawable.ref.y = dotY;
}
6 changes: 6 additions & 0 deletions examples/realtime_example/dart/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: worm_example
environment:
sdk: ">=2.17.0 <3.0.0"

dependencies:
ffi: ^2.0.1
4 changes: 4 additions & 0 deletions examples/realtime_example/drawable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "drawable.h"

#include "cute.h"
using namespace Cute;
15 changes: 15 additions & 0 deletions examples/realtime_example/drawable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <dart_api.h>
#include <cute.h>
using namespace Cute;

class Drawable {
public:
int x;
int y;
int width;
int height;

Color color;
};
Loading

0 comments on commit fa78740

Please sign in to comment.