Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new branch for spine 4.1 version & update runtime #98

Open
wants to merge 18 commits into
base: 4.1
Choose a base branch
from
Open
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# We'll let Git's auto-detection algorithm infer if a file is text. If it is,
# enforce LF line endings regardless of OS or git configurations.
* text=auto eol=lf
e2e/fixtures/** filter=lfs diff=lfs merge=lfs -text
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ tsconfig.tsbuildinfo
package-lock.json
.aci.yml
LEGAL.md
coverage
e2e/videos/*
e2e/screenshots/*
e2e/downloads/*
e2e/diff/*
e2e/.dev/mpa
110 changes: 67 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@


# Galacean Engine spine runtime
![Jun-12-2021 18-37-22.gif](https://gw.alipayobjects.com/mdn/mybank_yul/afts/img/A*am1ySYTDBQAAAAAAAAAAAAAAARQnAQ)
# Galacean Engine Spine Runtime


![](https://img.shields.io/npm/v/@galacean/engine-spine#id=QfHW0&originHeight=20&originWidth=80&originalType=binary&ratio=1&status=done&style=none)
Expand All @@ -10,70 +9,95 @@

---

[@galacean/engine-spine](https://www.npmjs.com/package/@galacean/engine-spine) is the Spine runtime module for the [Galacean engine](https://github.com/galacean/engine), providing efficient support for Spine animations. This package enables developers to seamlessly integrate and use Spine animations, delivering smooth skeletal animation effects optimized for both web and mobile platforms.

##
## Installation

Spine runtime for [Galacean engine](https://github.com/galacean/engine).
##
## Usage
Install **@galacean/engine-spine** via npm:


```typescript
import { SpineAnimation } from '@galacean/engine-spine';

// init oasis
addSpine();

async function addSpine() {
const spineEntity = await engine.resourceManager.load(
{
url: 'https://sbfkcel.github.io/pixi-spine-debug/assets/spine/spineboy-pro.json',
type: 'spine',
},
);
rootEntity.addChild(spineEntity);
const spineAnimation = spineEntity.getComponent(SpineAnimation);
spineAnimation.state.setAnimation(0, 'walk', true);
}
```bash
npm install @galacean/engine-spine
```


## npm
```sh
npm install @galacean/engine-spine
## Quick Start

Here's a simple example to get started with **@galacean/engine-spine**:

```typescript
import { SpineAnimationRenderer } from '@galacean/engine-spine';

// First setup for galacean engine, get scene and create root entity.
// Find setup code here:

// And then load spine resource and instantiate a spine entity with the resource.
const spineResource = await engine.resourceManager.load({
url: 'https://mdn.alipayobjects.com/huamei_kz4wfo/uri/file/as/2/kz4wfo/4/mp/yKbdfgijyLGzQDyQ/spineboy/spineboy.json',
type: 'spine',
});
const spineEntity = spineResource.instantiate();
rootEntity.addChild(spineEntity);
```

## API Documentation

For a detailed overview of the API, including all classes, methods, and properties, please refer to the [Full API Documentation](https://galacean.antgroup.com/engine/en/docs/graphics/2D/spine/api/).


## Version
@galacean/engine-spine currently only supports spine version 3.8
## Version Compatibility

### Package and Spine Version Compatibility

## Feature
| Package Version | Spine Version |
|-----------------|-----------------------|
| Below 4.0 | Spine 3.8 |
| 4.0 | Spine 4.0 |
| 4.1 | Spine 4.1 |
| 4.2 | Spine 4.2 |
| 4.x (e.g., 4.0, 4.1) | Corresponds to Spine x.x |
| 4.x.y (minor version `y`) | Independent from Spine |

- Simple in usage
- High performance.
- Intergrated with galacean engine.
- Component based API.
> Note: Ensure that the package version aligns with the corresponding Spine editor version for compatibility.

### Package and Galacean Engine Version Compatibility

| Package Version | Galacean Engine Version |
|-----------------|-------------------------|
| 4.0 and above | 1.3 and above |
| Below 4.0 (e.g., 1.2.0) | 1.2 |

## Contributing
Everyone is welcome to join us! Whether you find a bug, have a great feature request or you fancy owning a task from the road map feel free to get in touch.
> Note: Please verify that the versions of both the package and the Galacean Engine are compatible, as mismatched versions may cause unexpected issues.

Make sure to read the [Contributing Guide](.github/HOW_TO_CONTRIBUTE.md) before submitting changes.

## Building and Development

## Links
To set up the project for development and build it for production, follow these steps:

- [Examples](https://oasisengine.cn/#/examples/latest/spine-animation)
- [Documentation](https://oasisengine.cn/#/docs/latest/cn/spine)
- [GalaceanEngine](https://oasisengine.cn/)
1. **Install dependencies**:
```bash
npm install
```
2. **Start development environment**:
```bash
npm run dev
```
3. **Build for production**:
```bash
npm run build
```
4. **Run examples**:
```bash
npm run example
```



## License
## Links
- [Examples](https://galacean.antgroup.com/engine/en/docs/graphics/2D/spine/example/) - View usage examples for common scenarios.
- [User Guide](https://galacean.antgroup.com/engine/en/docs/graphics/2D/spine/overview/) - Comprehensive guide for using this package within the Galacean editor and in scripts.
- [API Reference](https://galacean.antgroup.com/engine/en/docs/graphics/2D/spine/api/) - Complete API documentation for all available classes, methods, and properties.


The Oasis Engine is released under the [MIT](https://opensource.org/licenses/MIT) license. See LICENSE file.
## License
The Galacean Engine is released under the [MIT](https://opensource.org/licenses/MIT) license. See LICENSE file.
6 changes: 6 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
"presets": [
"@babel/preset-env"
],
"plugins": ["@babel/plugin-proposal-class-properties"]
};
78 changes: 78 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { defineConfig } from "cypress";
import { compare } from "odiff-bin";

const path = require("path");
const fs = require("fs-extra");

const downloadDirectory = path.join(__dirname, "e2e/downloads");
let isRunningInCommandLine = false;
export default defineConfig({
e2e: {
viewportWidth: 1200,
viewportHeight: 800,
baseUrl: "http://localhost:5175",
defaultCommandTimeout: 60000,
fileServerFolder: "e2e",
supportFile: "e2e/support/e2e.ts",
fixturesFolder: "e2e/fixtures",
screenshotsFolder: "e2e/screenshots",
videosFolder: "e2e/videos",
specPattern: "e2e/tests/*.cy.ts",
downloadsFolder: "e2e/downloads",
video: false,
setupNodeEvents(on, config) {
// implement node event listeners here
on("before:browser:launch", (browser, launchOptions) => {
console.log("launching browser %s is headless? %s", browser.name, browser.isHeadless);
// supply the absolute path to an unpacked extension's folder
// NOTE: extensions cannot be loaded in headless Chrome
if (fs.existsSync("e2e/diff")) {
fs.rmdirSync("e2e/diff", { recursive: true });
}
if (browser.name === "chrome") {
launchOptions.preferences.default["download"] = {
default_directory: downloadDirectory
};
}
if (browser.isHeadless) {
isRunningInCommandLine = true;
}
launchOptions.args.push("--force-device-scale-factor=1");
return launchOptions;
}),
on("task", {
async compare({ fileName, options }) {
const baseFolder = "e2e/fixtures/originImage/";
const newFolder = path.join("e2e/downloads");
const diffFolder = path.join("e2e/diff", options.specFolder);
if (!fs.existsSync(diffFolder)) {
fs.mkdirSync(diffFolder, { recursive: true });
}
const baseImage = path.join(baseFolder, fileName);
const newImage = path.join(newFolder, fileName);
const diffImage = path.join(diffFolder, fileName);
console.log("comparing base image %s to the new image %s", baseImage, newImage);
if (options) {
console.log("odiff options %o", options);
}
const started = +new Date();

const result = await compare(baseImage, newImage, diffImage, options);
const finished = +new Date();
const elapsed = finished - started;
console.log("odiff took %dms", elapsed);

//@ts-ignore
if (result.match === false && result.diffPercentage <= 0.1) {
//@ts-ignore
result.match = true;
}

console.log(result);
return result;
}
});
}
},
chromeWebSecurity: false
});
Binary file added e2e/.dev/AlibabaSans.ttf
Binary file not shown.
39 changes: 39 additions & 0 deletions e2e/.dev/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Galacean Case</title>
</head>

<body>
<div class="container">
<div class="header">
<a class="logo" href="https://galacean.antgroup.com/" target="Home">
<img
src="https://mdn.alipayobjects.com/huamei_qbugvr/afts/img/A*ppQsSphM7uUAAAAAAAAAAAAADtKFAQ/original"
alt=""
/>
<span> Galacean </span>
</a>
</div>
<input
placeholder="search..."
class="search-bar"
id="searchBar"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
/>
<div class="nav-left">
<div class="item-list" id="itemList"></div>
</div>

<div class="nav-right">
<iframe id="iframe" allowfullscreen src="" frameborder="0"></iframe>
</div>
</div>

<script type="module" src="./index.js"></script>
</body>
</html>
76 changes: 76 additions & 0 deletions e2e/.dev/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import './index.sass';
import demoList from './mpa/.demoList.json';
const itemListDOM = document.getElementById('itemList');
const searchBarDOM = document.getElementById('searchBar');
const iframe = document.getElementById('iframe');
const items = []; // itemDOM,label

Object.keys(demoList).forEach((group) => {
const demos = demoList[group];
const groupDOM = document.createElement('div');
const demosDOM = document.createElement('ul');
itemListDOM.appendChild(groupDOM);
groupDOM.appendChild(demosDOM);

demos.forEach((item) => {
const { label, src } = item;
const itemDOM = document.createElement('a');

itemDOM.innerHTML = src;
itemDOM.title = `${src}`;
itemDOM.onclick = function () {
clickItem(itemDOM);
};
demosDOM.appendChild(itemDOM);

items.push({
itemDOM,
label,
src,
});
});
});

searchBarDOM.oninput = () => {
updateFilter(searchBar.value);
};

function updateFilter(value) {
const reg = new RegExp(value, 'i');

items.forEach(({ itemDOM, label, src }) => {
reg.lastIndex = 0;
if (reg.test(label) || reg.test(src)) {
itemDOM.classList.remove('hide');
} else {
itemDOM.classList.add('hide');
}
});
}

function clickItem(itemDOM) {
window.location.hash = `#mpa/${itemDOM.title}`;
}

function onHashChange() {
const hashPath = window.location.hash.split('#')[1];
if (!hashPath) {
clickItem(items[0].itemDOM);
return;
}
iframe.src = hashPath + '.html';

items.forEach(({ itemDOM }) => {
const itemPath = `mpa/${itemDOM.title}`;
if (itemPath === hashPath) {
itemDOM.classList.add('active');
} else {
itemDOM.classList.remove('active');
}
});
}

window.onhashchange = onHashChange;

// init
onHashChange();
Loading