mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-10 00:58:43 +08:00
Merge branch '4.3-beta' of https://github.com/EsotericSoftware/spine-runtimes into 4.3-beta
This commit is contained in:
commit
7656f4f7ef
63
.github/workflows/format-check.yml
vendored
63
.github/workflows/format-check.yml
vendored
@ -1,48 +1,28 @@
|
||||
name: Check format
|
||||
name: Check Formatting
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
check:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
|
||||
- name: Install OS dependencies (needed for act on ubuntu-latest)
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y --force-yes curl xz-utils libicu-dev git dos2unix
|
||||
wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb
|
||||
sudo apt install ./libtinfo5_6.3-2ubuntu0.1_amd64.deb
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache Clang
|
||||
id: cache-clang
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: clang
|
||||
key: ${{ runner.os }}-clang-13-0-1
|
||||
|
||||
- name: Install Clang
|
||||
if: steps.cache-clang.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
curl -L https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.1/clang+llvm-13.0.1-x86_64-linux-gnu-ubuntu-18.04.tar.xz --output clang.tar.xz
|
||||
tar -xf clang.tar.xz
|
||||
mv clang+llvm-13.0.1-x86_64-linux-gnu-ubuntu-18.04 clang
|
||||
- name: Setup clang-format
|
||||
run: ./formatters/setup-clang-format-docker.sh
|
||||
|
||||
- name: Install dotnet
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: "6.0.x"
|
||||
- run: dotnet tool install -g dotnet-format
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Install Node and dependenceis
|
||||
- name: Install Node and dependencies
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
- run: npm install -g typescript typescript-formatter
|
||||
node-version: "24"
|
||||
|
||||
- name: Install JDK
|
||||
uses: actions/setup-java@v3
|
||||
@ -50,14 +30,29 @@ jobs:
|
||||
distribution: 'zulu'
|
||||
java-version: "16"
|
||||
|
||||
- name: Install Haxe
|
||||
uses: krdlab/setup-haxe@v1
|
||||
with:
|
||||
haxe-version: '4.3.2'
|
||||
- run: haxelib install formatter
|
||||
|
||||
- name: Install Dart
|
||||
uses: dart-lang/setup-dart@v1
|
||||
with:
|
||||
sdk: '3.8.1'
|
||||
|
||||
- name: Check dart format version
|
||||
run: |
|
||||
dart format --version
|
||||
|
||||
- name: Format
|
||||
run: |
|
||||
export CLANGFORMAT=`pwd`/clang/bin/clang-format
|
||||
export PATH="$PATH:/root/.dotnet/tools"
|
||||
dotnet-format --version
|
||||
./formatters/format.sh
|
||||
find . -type f -name '*.cs' -exec perl -pi -e 's/\r\n/\n/g' '{}' +
|
||||
git diff
|
||||
./formatters/format-cpp.sh
|
||||
./formatters/format-csharp.sh
|
||||
./formatters/format-dart.sh
|
||||
./formatters/format-haxe.sh
|
||||
./formatters/format-java.sh
|
||||
./formatters/format-ts.sh
|
||||
git diff > format-diff.txt
|
||||
|
||||
- name: Archive formatting result
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -252,3 +252,5 @@ spine-libgdx/.project
|
||||
.clang-format
|
||||
spine-c/codegen/spine-cpp-types.json
|
||||
spine-flutter/example/devtools_options.yaml
|
||||
spine-glfw/.cache
|
||||
formatters/eclipse-formatter/format-diff.txt
|
||||
|
||||
@ -70,6 +70,7 @@ SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpaceInEmptyBlock: true
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
|
||||
@ -12,7 +12,7 @@ indent_style = tab
|
||||
tab_width = 4
|
||||
|
||||
# New line preferences
|
||||
end_of_line = crlf
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
#### .NET Coding Conventions ####
|
||||
|
||||
1
formatters/.gitignore
vendored
Normal file
1
formatters/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
eclipse-formatter/target/
|
||||
@ -1,11 +1,103 @@
|
||||
# Formatters
|
||||
This folder contains formatter configuration files to be used with IDEs as well as the [spotless](https://github.com/diffplug/spotless/blob/main/plugin-gradle/README.md) formatter expressed in the Gradle project in this directory.
|
||||
# Spine Runtimes Code Formatters
|
||||
|
||||
You will need the following on your `PATH`:
|
||||
This directory contains formatting scripts and tools to ensure consistent code style across all Spine runtime implementations.
|
||||
|
||||
- JDK 10+
|
||||
- clang-format 12.0.1 (i.e. `brew install clang-format`). Also set the environment variable `CLANGFORMAT` to the path of the `clang-format` executable.
|
||||
- dotnet format (i.e. `dotnet tool install -g dotnet-format`, comes with dotnet 6 out of the box)
|
||||
- tsfmt, (i.e. `npm install -g typescript-formatter`)
|
||||
## Scripts
|
||||
|
||||
To run the formatter, invoke the `format.sh` script. This will shuffle around the Gradle config files, invoke spotless, then undo the config file shuffling. Invoking `./gradlew spotlessApply` from the `formatters/` directory will not work.
|
||||
### format-cpp.sh
|
||||
Formats C/C++ source files using clang-format.
|
||||
- **Prerequisites**: clang-format 18.1.8
|
||||
- **Coverage**: All C/C++ files in spine-cpp, spine-c, spine-godot, spine-ue, spine-glfw, spine-sdl, spine-sfml, spine-cocos2dx, spine-ios, spine-flutter
|
||||
- **Configuration**: Uses .clang-format configuration file
|
||||
- **Behavior**: Batches all files in a single clang-format call for performance
|
||||
|
||||
### format-csharp.sh
|
||||
Formats C# source files using dotnet format.
|
||||
- **Prerequisites**: .NET SDK with dotnet format tool
|
||||
- **Coverage**: All C# files in spine-csharp, spine-monogame, spine-unity
|
||||
- **Configuration**: Uses .editorconfig (temporarily copied to each project)
|
||||
- **Behavior**: Runs with --no-restore and --verbosity quiet to suppress warnings
|
||||
|
||||
### format-dart.sh
|
||||
Formats Dart source files using dart format.
|
||||
- **Prerequisites**: Dart SDK
|
||||
- **Coverage**: All Dart files in spine-flutter
|
||||
- **Configuration**: Uses --page-width 120 parameter
|
||||
- **Behavior**: Formats all files in place
|
||||
|
||||
### format-haxe.sh
|
||||
Formats Haxe source files using haxelib formatter.
|
||||
- **Prerequisites**: Haxe and haxelib formatter package
|
||||
- **Coverage**: All Haxe files in spine-haxe
|
||||
- **Configuration**: Uses hxformat.json configuration file
|
||||
- **Behavior**: Formats all files in place
|
||||
|
||||
### format-java.sh
|
||||
Formats Java source files using a custom Eclipse formatter.
|
||||
- **Prerequisites**: Java JDK and Maven
|
||||
- **Coverage**: All Java files in spine-libgdx and spine-android
|
||||
- **Configuration**: Uses eclipse-formatter.xml configuration file
|
||||
- **Behavior**: Builds Eclipse formatter JAR if needed, only outputs changed files
|
||||
|
||||
### format-ts.sh
|
||||
Formats TypeScript source files using typescript-formatter.
|
||||
- **Prerequisites**: Node.js and npm
|
||||
- **Coverage**: All TypeScript files in spine-ts and tests
|
||||
- **Configuration**: Uses tsfmt.json configuration files
|
||||
- **Behavior**: Uses npx to auto-download formatter, validates tsfmt.json consistency
|
||||
|
||||
### setup-clang-format-docker.sh
|
||||
Helper script for GitHub Actions to set up clang-format via Docker.
|
||||
- **Prerequisites**: Docker
|
||||
- **Purpose**: Creates a wrapper script that runs clang-format 18.1.8 in a Docker container
|
||||
- **Usage**: Called by GitHub Actions workflow to ensure version consistency
|
||||
|
||||
## Configuration Files
|
||||
|
||||
- **.clang-format**: C/C++ formatting rules
|
||||
- **.editorconfig**: C# formatting rules
|
||||
- **eclipse-formatter.xml**: Java formatting rules for Eclipse formatter
|
||||
- **hxformat.json**: Haxe formatting rules
|
||||
|
||||
## Eclipse Formatter
|
||||
|
||||
The eclipse-formatter directory contains a Maven project that builds a standalone Eclipse code formatter:
|
||||
- **Source**: eclipse-formatter/src/main/java/com/esotericsoftware/spine/formatter/EclipseFormatter.java
|
||||
- **Build**: Automatically built by format-java.sh when the JAR doesn't exist or source is newer
|
||||
- **Output**: Only prints files that were actually modified
|
||||
|
||||
## GitHub Actions Workflow
|
||||
|
||||
The formatting check runs automatically on push and can be triggered manually:
|
||||
|
||||
1. **Workflow file**: .github/workflows/format-check-new.yml
|
||||
2. **Process**:
|
||||
- Sets up all required formatters and dependencies
|
||||
- Runs all format scripts
|
||||
- Captures any file changes to format-diff.txt
|
||||
- Uploads diff as artifact
|
||||
- Fails if any files were modified
|
||||
|
||||
### Docker-based clang-format
|
||||
|
||||
To ensure consistent formatting across local development and CI, the workflow uses Docker to run clang-format 18.1.8. The setup-clang-format-docker.sh script creates a wrapper that:
|
||||
- Mounts the project directory in the Docker container
|
||||
- Converts relative paths to absolute paths
|
||||
- Runs clang-format with the same version everywhere
|
||||
|
||||
## Local Development
|
||||
|
||||
To run formatters locally:
|
||||
|
||||
```bash
|
||||
cd formatters
|
||||
./format-cpp.sh # Format C/C++ files
|
||||
./format-csharp.sh # Format C# files
|
||||
./format-dart.sh # Format Dart files
|
||||
./format-haxe.sh # Format Haxe files
|
||||
./format-java.sh # Format Java files
|
||||
./format-ts.sh # Format TypeScript files
|
||||
./format.sh # Format everything
|
||||
```
|
||||
|
||||
Ensure you have the required tools installed for each formatter you want to run.
|
||||
@ -1,51 +0,0 @@
|
||||
buildscript { repositories { mavenCentral() }}
|
||||
|
||||
plugins {
|
||||
id "com.diffplug.spotless" version "5.14.0"
|
||||
}
|
||||
|
||||
spotless {
|
||||
lineEndings 'UNIX'
|
||||
|
||||
java {
|
||||
target 'spine-libgdx/**/*.java',
|
||||
'spine-android/**/*.java'
|
||||
eclipse().configFile('formatters/eclipse-formatter.xml')
|
||||
}
|
||||
|
||||
cpp {
|
||||
target 'spine-c/**/*.c',
|
||||
'spine-c/**/.h',
|
||||
'spine-cpp/**/*.cpp',
|
||||
'spine-cpp/**/.h',
|
||||
'spine-cocos2dx/src/**/*.cpp',
|
||||
'spine-cocos2dx/src/**/*.h',
|
||||
'spine-cocos2dx/example/Classes/**/*.cpp',
|
||||
'spine-cocos2dx/example/Classes/**/*.h',
|
||||
'spine-glfw/src/**/*.cpp',
|
||||
'spine-glfw/src/**/*.h',
|
||||
'spine-glfw/example/**/*.cpp',
|
||||
'spine-glfw/example/**/*.h',
|
||||
'spine-sdl/src/**/*.c',
|
||||
'spine-sdl/src/**/*.cpp',
|
||||
'spine-sdl/src/**/*.h',
|
||||
'spine-sdl/example/**/*.c',
|
||||
'spine-sdl/example/**/*.cpp',
|
||||
'spine-sdl/example/**/*.h',
|
||||
'spine-sfml/c/src/**/*.c',
|
||||
'spine-sfml/c/src/**/*.h',
|
||||
'spine-sfml/cpp/src/**/*.cpp',
|
||||
'spine-sfml/cpp/src/**/*.h',
|
||||
'spine-ue/**/*.cpp',
|
||||
'spine-ue/**/*.h',
|
||||
'spine-godot/spine_godot/*.cpp',
|
||||
'spine-godot/spine_godot/*.h'
|
||||
clangFormat("13.0.1").pathToExe("$System.env.CLANGFORMAT").style('file')
|
||||
}
|
||||
|
||||
typescript {
|
||||
target 'spine-ts/**/src/*.ts'
|
||||
targetExclude 'spine-ts/**/*.d.ts', 'spine-ts/**/node_modules/**/*.ts'
|
||||
tsfmt('7.2.2').tsfmtFile('formatters/tsfmt.json')
|
||||
}
|
||||
}
|
||||
106
formatters/eclipse-formatter/pom.xml
Normal file
106
formatters/eclipse-formatter/pom.xml
Normal file
@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.esotericsoftware.spine</groupId>
|
||||
<artifactId>eclipse-formatter</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<eclipse.version>4.26</eclipse.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Eclipse JDT Core for formatting -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jdt</groupId>
|
||||
<artifactId>org.eclipse.jdt.core</artifactId>
|
||||
<version>3.32.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Eclipse Text framework -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.platform</groupId>
|
||||
<artifactId>org.eclipse.text</artifactId>
|
||||
<version>3.12.300</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JFace Text -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.platform</groupId>
|
||||
<artifactId>org.eclipse.jface.text</artifactId>
|
||||
<version>3.22.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Eclipse Core Runtime -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.platform</groupId>
|
||||
<artifactId>org.eclipse.core.runtime</artifactId>
|
||||
<version>3.26.100</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Eclipse Equinox Common -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.platform</groupId>
|
||||
<artifactId>org.eclipse.equinox.common</artifactId>
|
||||
<version>3.17.100</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Eclipse Core Resources -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.platform</groupId>
|
||||
<artifactId>org.eclipse.core.resources</artifactId>
|
||||
<version>3.18.100</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Eclipse OSGi -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.platform</groupId>
|
||||
<artifactId>org.eclipse.osgi</artifactId>
|
||||
<version>3.18.300</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
</plugin>
|
||||
|
||||
<!-- Create executable JAR with dependencies -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.esotericsoftware.spine.formatter.EclipseFormatter</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,129 @@
|
||||
package com.esotericsoftware.spine.formatter;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import javax.xml.parsers.*;
|
||||
import org.w3c.dom.*;
|
||||
import org.eclipse.jdt.core.formatter.CodeFormatter;
|
||||
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
|
||||
import org.eclipse.jface.text.Document;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.text.edits.TextEdit;
|
||||
|
||||
public class EclipseFormatter {
|
||||
private static final String LINE_DELIMITER = "\n";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length < 2) {
|
||||
System.err.println("Usage: java -jar eclipse-formatter.jar <eclipse-formatter.xml> <file1.java> [file2.java ...]");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Load formatter settings from XML
|
||||
Map<String, String> options = loadFormatterSettings(args[0]);
|
||||
|
||||
// Create formatter
|
||||
CodeFormatter formatter = new DefaultCodeFormatter(options);
|
||||
|
||||
// Format each file
|
||||
int changedCount = 0;
|
||||
int errorCount = 0;
|
||||
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
try {
|
||||
if (formatFile(formatter, args[i])) {
|
||||
changedCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error formatting " + args[i] + ": " + e.getMessage());
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Formatting complete: " + changedCount + " files changed, " + errorCount + " errors");
|
||||
|
||||
if (errorCount > 0) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> loadFormatterSettings(String xmlPath) throws Exception {
|
||||
Map<String, String> settings = new HashMap<>();
|
||||
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
org.w3c.dom.Document doc = builder.parse(new File(xmlPath));
|
||||
|
||||
// Handle both direct settings and profile-based settings
|
||||
NodeList profiles = doc.getElementsByTagName("profile");
|
||||
if (profiles.getLength() > 0) {
|
||||
// Profile-based format (Eclipse export)
|
||||
Element profile = (Element) profiles.item(0);
|
||||
NodeList settingNodes = profile.getElementsByTagName("setting");
|
||||
|
||||
for (int i = 0; i < settingNodes.getLength(); i++) {
|
||||
Element setting = (Element) settingNodes.item(i);
|
||||
String id = setting.getAttribute("id");
|
||||
String value = setting.getAttribute("value");
|
||||
if (id != null && !id.isEmpty() && value != null) {
|
||||
settings.put(id, value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Direct settings format
|
||||
NodeList settingNodes = doc.getElementsByTagName("setting");
|
||||
|
||||
for (int i = 0; i < settingNodes.getLength(); i++) {
|
||||
Element setting = (Element) settingNodes.item(i);
|
||||
String id = setting.getAttribute("id");
|
||||
String value = setting.getAttribute("value");
|
||||
if (id != null && !id.isEmpty() && value != null) {
|
||||
settings.put(id, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Removed verbose output
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
private static boolean formatFile(CodeFormatter formatter, String filePath) throws Exception {
|
||||
Path path = Paths.get(filePath);
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
throw new FileNotFoundException("File not found: " + filePath);
|
||||
}
|
||||
|
||||
String content = Files.readString(path);
|
||||
|
||||
// Determine if it's a module-info.java file
|
||||
int kind = path.getFileName().toString().equals("module-info.java")
|
||||
? CodeFormatter.K_MODULE_INFO
|
||||
: CodeFormatter.K_COMPILATION_UNIT;
|
||||
kind |= CodeFormatter.F_INCLUDE_COMMENTS;
|
||||
|
||||
// Format the code
|
||||
TextEdit edit = formatter.format(kind, content, 0, content.length(), 0, LINE_DELIMITER);
|
||||
|
||||
if (edit == null) {
|
||||
throw new IllegalArgumentException("Cannot format file - invalid Java syntax or formatter configuration issue");
|
||||
}
|
||||
|
||||
// Apply the edit
|
||||
IDocument document = new Document(content);
|
||||
edit.apply(document);
|
||||
String formatted = document.get();
|
||||
|
||||
// Only write if content changed
|
||||
if (!content.equals(formatted)) {
|
||||
Files.writeString(path, formatted);
|
||||
System.out.println("Formatted: " + filePath);
|
||||
return true;
|
||||
} else {
|
||||
// Silent when no changes
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,8 +6,12 @@ echo "Formatting C/C++ files..."
|
||||
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
if [ ! -f "$dir/.clang-format" ]; then
|
||||
# Store original directory
|
||||
pushd "$dir" > /dev/null
|
||||
|
||||
if [ ! -f ".clang-format" ]; then
|
||||
echo "Error: .clang-format not found in formatters directory"
|
||||
popd > /dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -84,28 +88,20 @@ done
|
||||
|
||||
echo "Found ${#files[@]} C/C++ files to format"
|
||||
|
||||
# Format each file with progress
|
||||
count=0
|
||||
errors=0
|
||||
for file in "${files[@]}"; do
|
||||
count=$((count + 1))
|
||||
# Show progress every 10 files or for the last file
|
||||
if [ $((count % 10)) -eq 0 ] || [ $count -eq ${#files[@]} ]; then
|
||||
printf "\r[$count/${#files[@]}] Formatting: %-80s" "$(basename "$file")"
|
||||
fi
|
||||
|
||||
# Format the file and capture any errors
|
||||
if ! clang-format -i -style=file:"$dir/.clang-format" "$file" 2>/dev/null; then
|
||||
printf "\nError formatting: $file\n"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Clear the progress line and show completion
|
||||
printf "\r%-100s\r" " "
|
||||
# Format all files in one call - works for both Docker and native
|
||||
echo "Formatting ${#files[@]} files..."
|
||||
if ! clang-format -i -style=file:".clang-format" "${files[@]}" 2>&1; then
|
||||
echo "Error: clang-format failed"
|
||||
errors=1
|
||||
else
|
||||
errors=0
|
||||
fi
|
||||
|
||||
if [ $errors -gt 0 ]; then
|
||||
echo "Completed with $errors errors"
|
||||
fi
|
||||
|
||||
echo "C/C++ formatting complete"
|
||||
echo "C/C++ formatting complete"
|
||||
|
||||
# Return to original directory
|
||||
popd > /dev/null
|
||||
@ -6,20 +6,43 @@ echo "Formatting C# files..."
|
||||
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
if command -v dotnet-format &> /dev/null; then
|
||||
if command -v dotnet &> /dev/null; then
|
||||
# Store original directory
|
||||
pushd "$dir" > /dev/null
|
||||
|
||||
# Copy .editorconfig to C# directories
|
||||
cp .editorconfig ../spine-csharp/ 2>/dev/null || true
|
||||
cp .editorconfig ../spine-monogame/ 2>/dev/null || true
|
||||
cp .editorconfig ../spine-unity/ 2>/dev/null || true
|
||||
|
||||
dotnet-format ../spine-csharp/spine-csharp.sln || true
|
||||
dotnet-format -f ../spine-monogame || true
|
||||
dotnet-format -f ../spine-unity || true
|
||||
# Format spine-csharp
|
||||
pushd ../spine-csharp > /dev/null
|
||||
dotnet format spine-csharp.csproj --no-restore --verbosity quiet 2>/dev/null || echo "Warning: Some issues with spine-csharp formatting"
|
||||
popd > /dev/null
|
||||
|
||||
# Format spine-monogame
|
||||
pushd ../spine-monogame > /dev/null
|
||||
dotnet format --no-restore --verbosity quiet 2>/dev/null || echo "Warning: Some issues with spine-monogame formatting"
|
||||
popd > /dev/null
|
||||
|
||||
# Format spine-unity - look for .cs files directly
|
||||
if [ -d ../spine-unity ]; then
|
||||
echo "Formatting spine-unity C# files directly..."
|
||||
pushd ../spine-unity > /dev/null
|
||||
# Find all .cs files and format them using dotnet format whitespace
|
||||
find . -name "*.cs" -type f -not -path "./Library/*" -not -path "./Temp/*" -not -path "./obj/*" -not -path "./bin/*" | while read -r file; do
|
||||
dotnet format whitespace --include "$file" --no-restore 2>/dev/null || true
|
||||
done
|
||||
popd > /dev/null
|
||||
fi
|
||||
|
||||
# Clean up .editorconfig files
|
||||
rm -f ../spine-csharp/.editorconfig
|
||||
rm -f ../spine-monogame/.editorconfig
|
||||
rm -f ../spine-unity/.editorconfig
|
||||
|
||||
# Return to original directory
|
||||
popd > /dev/null
|
||||
else
|
||||
echo "Warning: dotnet-format not found. Skipping C# formatting."
|
||||
echo "Warning: dotnet not found. Skipping C# formatting."
|
||||
fi
|
||||
@ -4,12 +4,20 @@ set -e
|
||||
# Format Dart files
|
||||
echo "Formatting Dart files..."
|
||||
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
# Store original directory
|
||||
pushd "$dir" > /dev/null
|
||||
|
||||
if command -v dart &> /dev/null; then
|
||||
find .. -name "*.dart" \
|
||||
-not -path "*/.*" \
|
||||
-not -path "*/node_modules/*" \
|
||||
-not -path "*/build/*" \
|
||||
-exec dart format {} +
|
||||
-exec dart format --page-width 120 {} +
|
||||
else
|
||||
echo "Warning: dart not found. Skipping Dart formatting."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Return to original directory
|
||||
popd > /dev/null
|
||||
@ -4,12 +4,19 @@ set -e
|
||||
# Format Haxe files
|
||||
echo "Formatting Haxe files..."
|
||||
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
# Store original directory
|
||||
pushd "$dir" > /dev/null
|
||||
|
||||
if command -v haxelib &> /dev/null && haxelib list formatter &> /dev/null; then
|
||||
find .. -name "*.hx" \
|
||||
-not -path "*/.*" \
|
||||
-not -path "*/node_modules/*" \
|
||||
-not -path "*/build/*" \
|
||||
| xargs haxelib run formatter -s
|
||||
# Format spine-haxe directory
|
||||
if [ -d ../spine-haxe ]; then
|
||||
haxelib run formatter -s ../spine-haxe
|
||||
fi
|
||||
else
|
||||
echo "Warning: haxe formatter not found. Install with: haxelib install formatter"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Return to original directory
|
||||
popd > /dev/null
|
||||
@ -1,9 +1,42 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Format Java files with Spotless (keeping this for Eclipse formatter)
|
||||
# Format Java files with Eclipse formatter
|
||||
echo "Formatting Java files..."
|
||||
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
./formatters/gradlew -p formatters spotlessJavaApply --quiet
|
||||
# Store original directory
|
||||
pushd "$dir" > /dev/null
|
||||
|
||||
# Build the Eclipse formatter if needed
|
||||
jar_file="eclipse-formatter/target/eclipse-formatter-1.0.0-jar-with-dependencies.jar"
|
||||
src_file="eclipse-formatter/src/main/java/com/esotericsoftware/spine/formatter/EclipseFormatter.java"
|
||||
|
||||
if [ ! -f "$jar_file" ] || [ "$src_file" -nt "$jar_file" ]; then
|
||||
echo "Building Eclipse formatter..."
|
||||
pushd eclipse-formatter > /dev/null
|
||||
mvn -q clean package
|
||||
popd > /dev/null
|
||||
fi
|
||||
|
||||
# Find all Java files
|
||||
java_files=$(find ../spine-libgdx ../spine-android -name "*.java" -type f \
|
||||
-not -path "*/build/*" \
|
||||
-not -path "*/.gradle/*" \
|
||||
-not -path "*/bin/*" \
|
||||
-not -path "*/gen/*" \
|
||||
-not -path "*/target/*")
|
||||
|
||||
# Run the formatter
|
||||
if [ -n "$java_files" ]; then
|
||||
echo "Running Eclipse formatter on Java files..."
|
||||
java -jar eclipse-formatter/target/eclipse-formatter-1.0.0-jar-with-dependencies.jar \
|
||||
eclipse-formatter.xml \
|
||||
$java_files
|
||||
fi
|
||||
|
||||
echo "Java formatting complete"
|
||||
|
||||
# Return to original directory
|
||||
popd > /dev/null
|
||||
@ -4,6 +4,11 @@ set -e
|
||||
# Format Swift files
|
||||
echo "Formatting Swift files..."
|
||||
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
# Store original directory
|
||||
pushd "$dir" > /dev/null
|
||||
|
||||
if command -v swift-format &> /dev/null; then
|
||||
find .. -name "*.swift" \
|
||||
-not -path "*/.*" \
|
||||
@ -12,4 +17,7 @@ if command -v swift-format &> /dev/null; then
|
||||
| xargs swift-format -i
|
||||
else
|
||||
echo "Warning: swift-format not found. Install from https://github.com/apple/swift-format"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Return to original directory
|
||||
popd > /dev/null
|
||||
@ -6,13 +6,25 @@ echo "Formatting TypeScript files..."
|
||||
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
# Store original directory
|
||||
pushd "$dir" > /dev/null
|
||||
|
||||
# Check if tsfmt.json files match
|
||||
if ! cmp -s ../spine-ts/tsfmt.json ../tests/tsfmt.json; then
|
||||
echo -e "\033[1;31mERROR: spine-ts/tsfmt.json and tests/tsfmt.json differ!\033[0m"
|
||||
echo -e "\033[1;31mPlease sync them to ensure consistent formatting.\033[0m"
|
||||
popd > /dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Format TypeScript files
|
||||
cd ../spine-ts && npm run format && cd ../formatters
|
||||
cd ../tests && npm run format -r && cd ../formatters
|
||||
pushd ../spine-ts > /dev/null
|
||||
npm run format
|
||||
popd > /dev/null
|
||||
|
||||
pushd ../tests > /dev/null
|
||||
npm run format
|
||||
popd > /dev/null
|
||||
|
||||
# Return to original directory
|
||||
popd > /dev/null
|
||||
@ -31,10 +31,10 @@ show_help() {
|
||||
echo "Multiple language flags can be combined, e.g.: ./format.sh java ts"
|
||||
echo ""
|
||||
echo "Tools used:"
|
||||
echo " Java: Spotless with Eclipse formatter"
|
||||
echo " TypeScript: Biome"
|
||||
echo " Java: Eclipse formatter (via eclipse-formatter.xml)"
|
||||
echo " TypeScript: tsfmt (typescript-formatter)"
|
||||
echo " C/C++: clang-format"
|
||||
echo " C#: dotnet-format"
|
||||
echo " C#: dotnet format"
|
||||
echo " Haxe: haxe formatter"
|
||||
echo " Dart: dart format"
|
||||
echo " Swift: swift-format"
|
||||
|
||||
BIN
formatters/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
formatters/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@ -1,5 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||
172
formatters/gradlew
vendored
172
formatters/gradlew
vendored
@ -1,172 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
formatters/gradlew.bat
vendored
84
formatters/gradlew.bat
vendored
@ -1,84 +0,0 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@ -1,3 +0,0 @@
|
||||
include ':spine-libgdx:spine-libgdx'
|
||||
include ':spine-libgdx:spine-libgdx-tests'
|
||||
include ':spine-libgdx:spine-skeletonviewer'
|
||||
51
formatters/setup-clang-format-docker.sh
Executable file
51
formatters/setup-clang-format-docker.sh
Executable file
@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Setting up clang-format Docker wrapper..."
|
||||
|
||||
# Pull the Docker image with clang-format 18
|
||||
echo "Pulling Docker image..."
|
||||
docker pull silkeh/clang:18
|
||||
|
||||
# Create a wrapper script that runs clang-format in Docker
|
||||
echo "Creating wrapper script..."
|
||||
cat > /tmp/clang-format-wrapper <<'EOF'
|
||||
#!/bin/bash
|
||||
# Get the absolute path of the file being formatted
|
||||
args=()
|
||||
for arg in "$@"; do
|
||||
if [[ -f "$arg" ]]; then
|
||||
# Convert to absolute path
|
||||
args+=("$(realpath "$arg")")
|
||||
else
|
||||
args+=("$arg")
|
||||
fi
|
||||
done
|
||||
|
||||
# Find the project root (where .github directory is)
|
||||
current_dir="$PWD"
|
||||
while [[ "$current_dir" != "/" ]]; do
|
||||
if [[ -d "$current_dir/.github" ]]; then
|
||||
project_root="$current_dir"
|
||||
break
|
||||
fi
|
||||
current_dir="$(dirname "$current_dir")"
|
||||
done
|
||||
|
||||
# If we didn't find project root, use current directory's parent
|
||||
if [[ -z "$project_root" ]]; then
|
||||
project_root="$(dirname "$PWD")"
|
||||
fi
|
||||
|
||||
# Run docker with the project root mounted
|
||||
exec docker run --rm -i -v "$project_root:$project_root" -w "$PWD" silkeh/clang:18 clang-format "${args[@]}"
|
||||
EOF
|
||||
|
||||
# Install the wrapper
|
||||
sudo mv /tmp/clang-format-wrapper /usr/local/bin/clang-format
|
||||
sudo chmod +x /usr/local/bin/clang-format
|
||||
|
||||
# Verify version and location
|
||||
echo "Verifying installation..."
|
||||
which clang-format
|
||||
clang-format --version
|
||||
@ -32,7 +32,7 @@ fi
|
||||
|
||||
# Run codegen if requested
|
||||
if [ "$1" = "codegen" ]; then
|
||||
npx tsx codegen/src/index.ts
|
||||
npx -y tsx codegen/src/index.ts
|
||||
# Format the generated C++ files
|
||||
echo "Formatting generated C++ files..."
|
||||
../formatters/format.sh cpp
|
||||
|
||||
@ -133,7 +133,7 @@ Generated files are output to `../src/generated/`:
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
npx tsx src/index.ts
|
||||
npx -y tsx src/index.ts
|
||||
# The generated files will be in ../src/generated/
|
||||
```
|
||||
|
||||
|
||||
@ -1,113 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}</ProjectGuid>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>Spine</RootNamespace>
|
||||
<AssemblyName>spine-csharp</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
|
||||
<XnaPlatform>Windows</XnaPlatform>
|
||||
<XnaProfile>HiDef</XnaProfile>
|
||||
<XnaCrossPlatformGroupID>99dfd52d-8beb-4e5c-a68b-365be39e8064</XnaCrossPlatformGroupID>
|
||||
<XnaOutputType>Library</XnaOutputType>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;WINDOWS</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Net" />
|
||||
<Compile Include="src\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="src\Animation.cs" />
|
||||
<Compile Include="src\AnimationState.cs" />
|
||||
<Compile Include="src\AnimationStateData.cs" />
|
||||
<Compile Include="src\Atlas.cs" />
|
||||
<Compile Include="src\Attachments\AtlasAttachmentLoader.cs" />
|
||||
<Compile Include="src\Attachments\Attachment.cs" />
|
||||
<Compile Include="src\Attachments\AttachmentLoader.cs" />
|
||||
<Compile Include="src\Attachments\AttachmentType.cs" />
|
||||
<Compile Include="src\Attachments\BoundingBoxAttachment.cs" />
|
||||
<Compile Include="src\Attachments\ClippingAttachment.cs" />
|
||||
<Compile Include="src\Attachments\IHasTextureRegion.cs" />
|
||||
<Compile Include="src\Attachments\MeshAttachment.cs" />
|
||||
<Compile Include="src\Attachments\PathAttachment.cs" />
|
||||
<Compile Include="src\Attachments\PointAttachment.cs" />
|
||||
<Compile Include="src\Attachments\RegionAttachment.cs" />
|
||||
<Compile Include="src\Attachments\Sequence.cs" />
|
||||
<Compile Include="src\Attachments\VertexAttachment.cs" />
|
||||
<Compile Include="src\BlendMode.cs" />
|
||||
<Compile Include="src\Bone.cs" />
|
||||
<Compile Include="src\BoneData.cs" />
|
||||
<Compile Include="src\ConstraintData.cs" />
|
||||
<Compile Include="src\PhysicsConstraint.cs" />
|
||||
<Compile Include="src\PhysicsConstraintData.cs" />
|
||||
<Compile Include="src\SkeletonLoader.cs" />
|
||||
<Compile Include="src\TextureRegion.cs" />
|
||||
<Compile Include="src\Triangulator.cs" />
|
||||
<Compile Include="src\Event.cs" />
|
||||
<Compile Include="src\EventData.cs" />
|
||||
<Compile Include="src\ExposedList.cs" />
|
||||
<Compile Include="src\IkConstraint.cs" />
|
||||
<Compile Include="src\IkConstraintData.cs" />
|
||||
<Compile Include="src\IUpdatable.cs" />
|
||||
<Compile Include="src\Json.cs" />
|
||||
<Compile Include="src\MathUtils.cs" />
|
||||
<Compile Include="src\PathConstraint.cs" />
|
||||
<Compile Include="src\PathConstraintData.cs" />
|
||||
<Compile Include="src\Skeleton.cs" />
|
||||
<Compile Include="src\SkeletonBinary.cs" />
|
||||
<Compile Include="src\SkeletonBounds.cs" />
|
||||
<Compile Include="src\SkeletonClipping.cs" />
|
||||
<Compile Include="src\SkeletonData.cs" />
|
||||
<Compile Include="src\SkeletonJson.cs" />
|
||||
<Compile Include="src\Skin.cs" />
|
||||
<Compile Include="src\Slot.cs" />
|
||||
<Compile Include="src\SlotData.cs" />
|
||||
<Compile Include="src\TransformConstraint.cs" />
|
||||
<Compile Include="src\TransformConstraintData.cs" />
|
||||
<None Remove="src\ColorUnity.cs.meta" />
|
||||
<None Remove="src\ColorMono.cs.meta" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
|
||||
</Project>
|
||||
@ -1,23 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-csharp", "spine-csharp.csproj", "{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = spine-csharp.csproj
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@ -51,7 +51,7 @@ namespace Spine {
|
||||
}
|
||||
|
||||
public static implicit operator Color32F (Microsoft.Xna.Framework.Color xnaColor) {
|
||||
return new Color32F(xnaColor);
|
||||
return new Color32F(xnaColor);
|
||||
}
|
||||
|
||||
public static implicit operator Microsoft.Xna.Framework.Color (Color32F c) {
|
||||
|
||||
@ -36,7 +36,7 @@ namespace Spine {
|
||||
internal int bendDirection;
|
||||
internal bool compress, stretch;
|
||||
internal float mix, softness;
|
||||
|
||||
|
||||
public void Set (IkConstraintPose pose) {
|
||||
mix = pose.mix;
|
||||
softness = pose.softness;
|
||||
|
||||
@ -36,24 +36,28 @@ class AnimatedLogin extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
reportLeaks();
|
||||
final controller = SpineWidgetController(onInitialized: (controller) {
|
||||
controller.skeleton.setSkinByName("nate");
|
||||
controller.skeleton.setToSetupPose();
|
||||
controller.animationState.setAnimationByName(0, "login/look-left-down", true);
|
||||
});
|
||||
final controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
controller.skeleton.setSkinByName("nate");
|
||||
controller.skeleton.setToSetupPose();
|
||||
controller.animationState.setAnimationByName(0, "login/look-left-down", true);
|
||||
},
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Animated login')),
|
||||
body: Container(
|
||||
margin: const EdgeInsets.all(15.0),
|
||||
padding: const EdgeInsets.all(3.0),
|
||||
decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||
child: SpineWidget.fromAsset(
|
||||
"assets/chibi/chibi-stickers.atlas",
|
||||
"assets/chibi/chibi-stickers.skel",
|
||||
controller,
|
||||
boundsProvider: SkinAndAnimationBounds(skins: ["nate"], animation: "login/look-left-down"),
|
||||
sizedByBounds: true,
|
||||
)));
|
||||
appBar: AppBar(title: const Text('Animated login')),
|
||||
body: Container(
|
||||
margin: const EdgeInsets.all(15.0),
|
||||
padding: const EdgeInsets.all(3.0),
|
||||
decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||
child: SpineWidget.fromAsset(
|
||||
"assets/chibi/chibi-stickers.atlas",
|
||||
"assets/chibi/chibi-stickers.skel",
|
||||
controller,
|
||||
boundsProvider: SkinAndAnimationBounds(skins: ["nate"], animation: "login/look-left-down"),
|
||||
sizedByBounds: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,32 +8,38 @@ class AnimationStateEvents extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
reportLeaks();
|
||||
final controller = SpineWidgetController(onInitialized: (controller) {
|
||||
controller.skeleton.setScaleX(0.5);
|
||||
controller.skeleton.setScaleY(0.5);
|
||||
controller.skeleton.findSlot("gun")?.setColor(Color(1, 0, 0, 1));
|
||||
controller.animationStateData.setDefaultMix(0.2);
|
||||
controller.animationState.setAnimationByName(0, "walk", true).setListener((type, trackEntry, event) {
|
||||
print("Walk animation event $type");
|
||||
});
|
||||
controller.animationState.addAnimationByName(0, "jump", false, 2);
|
||||
controller.animationState.addAnimationByName(0, "run", true, 0).setListener((type, trackEntry, event) {
|
||||
print("Run animation event $type");
|
||||
});
|
||||
controller.animationState.setListener((type, trackEntry, event) {
|
||||
if (type == EventType.event) {
|
||||
print(
|
||||
"User event: { name: ${event?.getData().getName()}, intValue: ${event?.getIntValue()}, floatValue: ${event?.getFloatValue()}, stringValue: ${event?.getStringValue()} }");
|
||||
}
|
||||
});
|
||||
print("Current: ${controller.animationState.getCurrent(0)?.getAnimation().getName()}");
|
||||
});
|
||||
final controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
controller.skeleton.setScaleX(0.5);
|
||||
controller.skeleton.setScaleY(0.5);
|
||||
controller.skeleton.findSlot("gun")?.setColor(Color(1, 0, 0, 1));
|
||||
controller.animationStateData.setDefaultMix(0.2);
|
||||
controller.animationState.setAnimationByName(0, "walk", true).setListener((type, trackEntry, event) {
|
||||
print("Walk animation event $type");
|
||||
});
|
||||
controller.animationState.addAnimationByName(0, "jump", false, 2);
|
||||
controller.animationState.addAnimationByName(0, "run", true, 0).setListener((type, trackEntry, event) {
|
||||
print("Run animation event $type");
|
||||
});
|
||||
controller.animationState.setListener((type, trackEntry, event) {
|
||||
if (type == EventType.event) {
|
||||
print(
|
||||
"User event: { name: ${event?.getData().getName()}, intValue: ${event?.getIntValue()}, floatValue: ${event?.getFloatValue()}, stringValue: ${event?.getStringValue()} }",
|
||||
);
|
||||
}
|
||||
});
|
||||
print("Current: ${controller.animationState.getCurrent(0)?.getAnimation().getName()}");
|
||||
},
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Animation State Listener')),
|
||||
body: Column(children: [
|
||||
appBar: AppBar(title: const Text('Animation State Listener')),
|
||||
body: Column(
|
||||
children: [
|
||||
const Text("See output in console!"),
|
||||
Expanded(child: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller))
|
||||
]));
|
||||
Expanded(child: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,36 +38,40 @@ class DebugRendering extends StatelessWidget {
|
||||
reportLeaks();
|
||||
|
||||
const debugRenderer = DebugRenderer();
|
||||
final controller = SpineWidgetController(onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "walk", true);
|
||||
}, onBeforePaint: (controller, canvas) {
|
||||
// Save the current transform and other canvas state
|
||||
canvas.save();
|
||||
final controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "walk", true);
|
||||
},
|
||||
onBeforePaint: (controller, canvas) {
|
||||
// Save the current transform and other canvas state
|
||||
canvas.save();
|
||||
|
||||
// Get the current canvas transform an invert it, so we can work in the
|
||||
// canvas coordinate system.
|
||||
final currentMatrix = canvas.getTransform();
|
||||
final invertedMatrix = Matrix4.tryInvert(Matrix4.fromFloat64List(currentMatrix));
|
||||
if (invertedMatrix != null) {
|
||||
canvas.transform(invertedMatrix.storage);
|
||||
}
|
||||
// Get the current canvas transform an invert it, so we can work in the
|
||||
// canvas coordinate system.
|
||||
final currentMatrix = canvas.getTransform();
|
||||
final invertedMatrix = Matrix4.tryInvert(Matrix4.fromFloat64List(currentMatrix));
|
||||
if (invertedMatrix != null) {
|
||||
canvas.transform(invertedMatrix.storage);
|
||||
}
|
||||
|
||||
// Draw something.
|
||||
final Paint paint = Paint()
|
||||
..color = Colors.black
|
||||
..strokeWidth = 2.0;
|
||||
// Draw something.
|
||||
final Paint paint = Paint()
|
||||
..color = Colors.black
|
||||
..strokeWidth = 2.0;
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(0, 0),
|
||||
Offset(canvas.getLocalClipBounds().width, canvas.getLocalClipBounds().height),
|
||||
paint,
|
||||
);
|
||||
canvas.drawLine(
|
||||
Offset(0, 0),
|
||||
Offset(canvas.getLocalClipBounds().width, canvas.getLocalClipBounds().height),
|
||||
paint,
|
||||
);
|
||||
|
||||
// Restore the old transform and canvas state
|
||||
canvas.restore();
|
||||
}, onAfterPaint: (controller, canvas, commands) {
|
||||
debugRenderer.render(controller.drawable, canvas, commands);
|
||||
});
|
||||
// Restore the old transform and canvas state
|
||||
canvas.restore();
|
||||
},
|
||||
onAfterPaint: (controller, canvas, commands) {
|
||||
debugRenderer.render(controller.drawable, canvas, commands);
|
||||
},
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Debug Renderer')),
|
||||
|
||||
@ -84,23 +84,26 @@ class DressUpState extends State<DressUp> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final controller = SpineWidgetController(onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "dance", true);
|
||||
});
|
||||
final controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "dance", true);
|
||||
},
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Dress Up')),
|
||||
body: _skinImages.isEmpty
|
||||
? const SizedBox()
|
||||
: Row(children: [
|
||||
appBar: AppBar(title: const Text('Dress Up')),
|
||||
body: _skinImages.isEmpty
|
||||
? const SizedBox()
|
||||
: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: thumbnailSize,
|
||||
child: ListView(
|
||||
children: _skinImages.keys.map((skinName) {
|
||||
var rawImageData = _skinImages[skinName]!;
|
||||
var image = Image(image: RawImageProvider(rawImageData));
|
||||
var box = SizedBox(width: 200, height: 200, child: image);
|
||||
return GestureDetector(
|
||||
children: _skinImages.keys.map((skinName) {
|
||||
var rawImageData = _skinImages[skinName]!;
|
||||
var image = Image(image: RawImageProvider(rawImageData));
|
||||
var box = SizedBox(width: 200, height: 200, child: image);
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
_toggleSkin(skinName);
|
||||
setState(() {});
|
||||
@ -114,16 +117,22 @@ class DressUpState extends State<DressUp> {
|
||||
color: Colors.grey,
|
||||
backgroundBlendMode: painting.BlendMode.saturation,
|
||||
),
|
||||
child: box));
|
||||
}).toList()),
|
||||
child: box,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SpineWidget.fromDrawable(
|
||||
_drawable,
|
||||
controller,
|
||||
boundsProvider: SkinAndAnimationBounds(skins: ["full-skins/girl"]),
|
||||
))
|
||||
]));
|
||||
child: SpineWidget.fromDrawable(
|
||||
_drawable,
|
||||
controller,
|
||||
boundsProvider: SkinAndAnimationBounds(skins: ["full-skins/girl"]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -50,8 +50,8 @@ class SpineComponent extends PositionComponent {
|
||||
Anchor super.anchor = Anchor.topLeft,
|
||||
super.children,
|
||||
super.priority,
|
||||
}) : _ownsDrawable = ownsDrawable,
|
||||
_boundsProvider = boundsProvider {
|
||||
}) : _ownsDrawable = ownsDrawable,
|
||||
_boundsProvider = boundsProvider {
|
||||
_drawable.update(0);
|
||||
_bounds = _boundsProvider.computeBounds(_drawable);
|
||||
size = Vector2(_bounds.width, _bounds.height);
|
||||
@ -69,15 +69,17 @@ class SpineComponent extends PositionComponent {
|
||||
Iterable<Component>? children,
|
||||
int? priority,
|
||||
}) async {
|
||||
return SpineComponent(await SkeletonDrawable.fromAsset(atlasFile, skeletonFile, bundle: bundle),
|
||||
ownsDrawable: true,
|
||||
boundsProvider: boundsProvider,
|
||||
position: position,
|
||||
scale: scale,
|
||||
angle: angle,
|
||||
anchor: anchor,
|
||||
children: children,
|
||||
priority: priority);
|
||||
return SpineComponent(
|
||||
await SkeletonDrawable.fromAsset(atlasFile, skeletonFile, bundle: bundle),
|
||||
ownsDrawable: true,
|
||||
boundsProvider: boundsProvider,
|
||||
position: position,
|
||||
scale: scale,
|
||||
angle: angle,
|
||||
anchor: anchor,
|
||||
children: children,
|
||||
priority: priority,
|
||||
);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
@ -114,8 +116,13 @@ class SimpleFlameExample extends FlameGame {
|
||||
// Load the Spineboy atlas and skeleton data from asset files
|
||||
// and create a SpineComponent from them, scaled down and
|
||||
// centered on the screen
|
||||
spineboy = await SpineComponent.fromAssets("assets/spineboy.atlas", "assets/spineboy-pro.json",
|
||||
scale: Vector2(0.4, 0.4), anchor: Anchor.center, position: Vector2(size.x / 2, size.y / 2));
|
||||
spineboy = await SpineComponent.fromAssets(
|
||||
"assets/spineboy.atlas",
|
||||
"assets/spineboy-pro.json",
|
||||
scale: Vector2(0.4, 0.4),
|
||||
anchor: Anchor.center,
|
||||
position: Vector2(size.x / 2, size.y / 2),
|
||||
);
|
||||
|
||||
// Set the "walk" animation on track 0 in looping mode
|
||||
spineboy.animationState.setAnimationByName(0, "walk", true);
|
||||
@ -137,7 +144,7 @@ class DragonExample extends FlameGame {
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
cachedAtlas = await Atlas.fromAsset("assets/dragon.atlas");
|
||||
cachedSkeletonData = await SkeletonData.fromAsset(cachedAtlas, "assets/dragon-ess.skel");
|
||||
cachedSkeletonData = await SkeletonData.fromAsset(cachedAtlas, "assets/dragon-ess.skel");
|
||||
final drawable = SkeletonDrawable(cachedAtlas, cachedSkeletonData, false);
|
||||
dragon = SpineComponent(
|
||||
drawable,
|
||||
@ -205,6 +212,9 @@ class SpineFlameGameWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(appBar: AppBar(title: const Text('Flame Integration')), body: GameWidget(game: game));
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Flame Integration')),
|
||||
body: GameWidget(game: game),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,19 +45,22 @@ class IkFollowingState extends State<IkFollowing> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
controller = SpineWidgetController(onInitialized: (controller) {
|
||||
// Set the walk animation on track 0, let it loop
|
||||
controller.animationState.setAnimationByName(0, "walk", true);
|
||||
controller.animationState.setAnimationByName(1, "aim", true);
|
||||
}, onAfterUpdateWorldTransforms: (controller) {
|
||||
final worldPosition = crossHairPosition;
|
||||
if (worldPosition == null) return;
|
||||
final bone = controller.skeleton.findBone("crosshair")!;
|
||||
final parent = bone.getParent()!;
|
||||
final position = parent.worldToLocal(worldPosition.dx, worldPosition.dy);
|
||||
bone.setX(position.x);
|
||||
bone.setY(position.y);
|
||||
});
|
||||
controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
// Set the walk animation on track 0, let it loop
|
||||
controller.animationState.setAnimationByName(0, "walk", true);
|
||||
controller.animationState.setAnimationByName(1, "aim", true);
|
||||
},
|
||||
onAfterUpdateWorldTransforms: (controller) {
|
||||
final worldPosition = crossHairPosition;
|
||||
if (worldPosition == null) return;
|
||||
final bone = controller.skeleton.findBone("crosshair")!;
|
||||
final parent = bone.getParent()!;
|
||||
final position = parent.worldToLocal(worldPosition.dx, worldPosition.dy);
|
||||
bone.setX(position.x);
|
||||
bone.setY(position.y);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _updateBonePosition(Offset position) {
|
||||
@ -69,11 +72,17 @@ class IkFollowingState extends State<IkFollowing> {
|
||||
reportLeaks();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('IK Following')),
|
||||
body: GestureDetector(
|
||||
onPanDown: (drag) => _updateBonePosition(drag.localPosition),
|
||||
onPanUpdate: (drag) => _updateBonePosition(drag.localPosition),
|
||||
child: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller, alignment: Alignment.centerLeft,),
|
||||
));
|
||||
appBar: AppBar(title: const Text('IK Following')),
|
||||
body: GestureDetector(
|
||||
onPanDown: (drag) => _updateBonePosition(drag.localPosition),
|
||||
onPanUpdate: (drag) => _updateBonePosition(drag.localPosition),
|
||||
child: SpineWidget.fromAsset(
|
||||
"assets/spineboy.atlas",
|
||||
"assets/spineboy-pro.skel",
|
||||
controller,
|
||||
alignment: Alignment.centerLeft,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,130 +46,96 @@ class ExampleSelector extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
const spacer = SizedBox(height: 10);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Spine Examples')),
|
||||
body: Center(
|
||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||
ElevatedButton(
|
||||
child: const Text('Simple Animation'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const SimpleAnimation(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Pause/Play animation'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const PlayPauseAnimation(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Animation State Listener'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const AnimationStateEvents(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Debug Rendering'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const DebugRendering(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Dress Up'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const DressUp(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('IK Following'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const IkFollowing(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Physics'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const PhysicsTest(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Flame: Simple Example'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => SpineFlameGameWidget(SimpleFlameExample()),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Flame: Pre-load and share Spine data'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => SpineFlameGameWidget(PreloadAndShareSpineDataExample()),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Flame: Dragon Example'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => SpineFlameGameWidget(DragonExample()),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
])));
|
||||
appBar: AppBar(title: const Text('Spine Examples')),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
child: const Text('Simple Animation'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const SimpleAnimation()));
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Pause/Play animation'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const PlayPauseAnimation()));
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Animation State Listener'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const AnimationStateEvents()));
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Debug Rendering'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const DebugRendering()));
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Dress Up'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const DressUp()));
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('IK Following'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const IkFollowing()));
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Physics'),
|
||||
onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const PhysicsTest()));
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Flame: Simple Example'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(builder: (context) => SpineFlameGameWidget(SimpleFlameExample())),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Flame: Pre-load and share Spine data'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => SpineFlameGameWidget(PreloadAndShareSpineDataExample()),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
ElevatedButton(
|
||||
child: const Text('Flame: Dragon Example'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(builder: (context) => SpineFlameGameWidget(DragonExample())),
|
||||
);
|
||||
},
|
||||
),
|
||||
spacer,
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -43,9 +43,11 @@ class PlayPauseAnimationState extends State<PlayPauseAnimation> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = SpineWidgetController(onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "flying", true);
|
||||
});
|
||||
controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "flying", true);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _togglePlay() {
|
||||
|
||||
@ -46,26 +46,29 @@ class PhysicsState extends State<PhysicsTest> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
controller = SpineWidgetController(onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "eyeblink-long", true);
|
||||
controller.animationState.setAnimationByName(1, "wings-and-feet", true);
|
||||
}, onAfterUpdateWorldTransforms: (controller) {
|
||||
if (lastMousePosition == null) {
|
||||
lastMousePosition = mousePosition;
|
||||
return;
|
||||
}
|
||||
if (mousePosition == null) {
|
||||
return;
|
||||
}
|
||||
controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
controller.animationState.setAnimationByName(0, "eyeblink-long", true);
|
||||
controller.animationState.setAnimationByName(1, "wings-and-feet", true);
|
||||
},
|
||||
onAfterUpdateWorldTransforms: (controller) {
|
||||
if (lastMousePosition == null) {
|
||||
lastMousePosition = mousePosition;
|
||||
return;
|
||||
}
|
||||
if (mousePosition == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final dx = mousePosition!.dx - lastMousePosition!.dx;
|
||||
final dy = mousePosition!.dy - lastMousePosition!.dy;
|
||||
final position = controller.skeleton.getPosition();
|
||||
position.x += dx;
|
||||
position.y += dy;
|
||||
controller.skeleton.setPosition(position.x, position.y);
|
||||
lastMousePosition = mousePosition;
|
||||
});
|
||||
final dx = mousePosition!.dx - lastMousePosition!.dx;
|
||||
final dy = mousePosition!.dy - lastMousePosition!.dy;
|
||||
final position = controller.skeleton.getPosition();
|
||||
position.x += dx;
|
||||
position.y += dy;
|
||||
controller.skeleton.setPosition(position.x, position.y);
|
||||
lastMousePosition = mousePosition;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _updateBonePosition(Offset position) {
|
||||
@ -77,11 +80,12 @@ class PhysicsState extends State<PhysicsTest> {
|
||||
reportLeaks();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Physics (drag anywhere)')),
|
||||
body: GestureDetector(
|
||||
onPanDown: (drag) => _updateBonePosition(drag.localPosition),
|
||||
onPanUpdate: (drag) => _updateBonePosition(drag.localPosition),
|
||||
child: SpineWidget.fromAsset("assets/celestial-circus.atlas", "assets/celestial-circus-pro.skel", controller),
|
||||
));
|
||||
appBar: AppBar(title: const Text('Physics (drag anywhere)')),
|
||||
body: GestureDetector(
|
||||
onPanDown: (drag) => _updateBonePosition(drag.localPosition),
|
||||
onPanUpdate: (drag) => _updateBonePosition(drag.localPosition),
|
||||
child: SpineWidget.fromAsset("assets/celestial-circus.atlas", "assets/celestial-circus-pro.skel", controller),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,18 +36,20 @@ class SimpleAnimation extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
reportLeaks();
|
||||
final controller = SpineWidgetController(onInitialized: (controller) {
|
||||
// Set the default mixing time between animations
|
||||
controller.animationState.getData().setDefaultMix(0.2);
|
||||
// Set the portal animation on track 0
|
||||
controller.animationState.setAnimationByName(0, "portal", true);
|
||||
// Queue the run animation after the portal animation
|
||||
controller.animationState.addAnimationByName(0, "run", true, 0);
|
||||
});
|
||||
final controller = SpineWidgetController(
|
||||
onInitialized: (controller) {
|
||||
// Set the default mixing time between animations
|
||||
controller.animationState.getData().setDefaultMix(0.2);
|
||||
// Set the portal animation on track 0
|
||||
controller.animationState.setAnimationByName(0, "portal", true);
|
||||
// Queue the run animation after the portal animation
|
||||
controller.animationState.addAnimationByName(0, "run", true, 0);
|
||||
},
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Simple Animation')),
|
||||
body: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller)
|
||||
body: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,8 +91,9 @@ Future<SpineFlutterFFI> initSpineFlutterFFI(bool useStaticLinkage) async {
|
||||
registerOpaqueType<spine_skin_entries_wrapper>();
|
||||
|
||||
await js.importLibrary('assets/packages/spine_flutter/lib/assets/libspine_flutter.js');
|
||||
Uint8List wasmBinaries =
|
||||
(await rootBundle.load('packages/spine_flutter/lib/assets/libspine_flutter.wasm')).buffer.asUint8List();
|
||||
Uint8List wasmBinaries = (await rootBundle.load(
|
||||
'packages/spine_flutter/lib/assets/libspine_flutter.wasm',
|
||||
)).buffer.asUint8List();
|
||||
_module = await EmscriptenModule.compile(wasmBinaries, 'libspine_flutter');
|
||||
}
|
||||
Module? m = _module;
|
||||
|
||||
@ -32,12 +32,7 @@ class RawImageProvider extends ImageProvider<_RawImageKey> {
|
||||
final double? scale;
|
||||
final int? targetWidth;
|
||||
final int? targetHeight;
|
||||
RawImageProvider(
|
||||
this.image, {
|
||||
this.scale = 1.0,
|
||||
this.targetWidth,
|
||||
this.targetHeight,
|
||||
});
|
||||
RawImageProvider(this.image, {this.scale = 1.0, this.targetWidth, this.targetHeight});
|
||||
|
||||
@override
|
||||
ImageStreamCompleter loadImage(_RawImageKey key, ImageDecoderCallback decode) {
|
||||
@ -69,8 +64,7 @@ class RawImageProvider extends ImageProvider<_RawImageKey> {
|
||||
debugPrint('ImageDescriptor: ${descriptor.width}x${descriptor.height}');
|
||||
return true;
|
||||
}());
|
||||
return descriptor.instantiateCodec(
|
||||
targetWidth: targetWidth, targetHeight: targetHeight);
|
||||
return descriptor.instantiateCodec(targetWidth: targetWidth, targetHeight: targetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,16 +99,10 @@ class RawImageData {
|
||||
final int height;
|
||||
final ui.PixelFormat pixelFormat;
|
||||
|
||||
RawImageData(
|
||||
this.pixels,
|
||||
this.width,
|
||||
this.height, {
|
||||
this.pixelFormat = ui.PixelFormat.rgba8888,
|
||||
});
|
||||
RawImageData(this.pixels, this.width, this.height, {this.pixelFormat = ui.PixelFormat.rgba8888});
|
||||
|
||||
_RawImageKey? _key;
|
||||
_RawImageKey _obtainKey() {
|
||||
return _key ??=
|
||||
_RawImageKey(width, height, pixelFormat.index, md5.convert(pixels));
|
||||
return _key ??= _RawImageKey(width, height, pixelFormat.index, md5.convert(pixels));
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
|
||||
import 'ffi_proxy.dart';
|
||||
import 'init.dart' if (dart.library.html) 'init_web.dart';
|
||||
import 'spine_flutter_bindings_generated.dart';
|
||||
@ -137,9 +136,13 @@ class Atlas {
|
||||
Map<BlendMode, Paint> paints = {};
|
||||
for (final blendMode in BlendMode.values) {
|
||||
paints[blendMode] = Paint()
|
||||
..shader = ImageShader(image, TileMode.clamp, TileMode.clamp, Matrix4
|
||||
.identity()
|
||||
.storage, filterQuality: Atlas.filterQuality)
|
||||
..shader = ImageShader(
|
||||
image,
|
||||
TileMode.clamp,
|
||||
TileMode.clamp,
|
||||
Matrix4.identity().storage,
|
||||
filterQuality: Atlas.filterQuality,
|
||||
)
|
||||
..isAntiAlias = true
|
||||
..blendMode = blendMode.canvasBlendMode;
|
||||
}
|
||||
@ -747,8 +750,12 @@ class BoneData {
|
||||
/// rendered at runtime.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_bone_data_get_color(_data);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -797,7 +804,15 @@ class Bone {
|
||||
///
|
||||
/// See [World transform](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
|
||||
/// Runtimes Guide.
|
||||
void updateWorldTransformWith(double x, double y, double rotation, double scaleX, double scaleY, double shearX, double shearY) {
|
||||
void updateWorldTransformWith(
|
||||
double x,
|
||||
double y,
|
||||
double rotation,
|
||||
double scaleX,
|
||||
double scaleY,
|
||||
double shearX,
|
||||
double shearY,
|
||||
) {
|
||||
_bindings.spine_bone_update_world_transform_with(_bone, x, y, rotation, scaleX, scaleY, shearX, shearY);
|
||||
}
|
||||
|
||||
@ -1123,8 +1138,12 @@ class SlotData {
|
||||
/// color tinting.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_slot_data_get_color(_data);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -1135,8 +1154,12 @@ class SlotData {
|
||||
/// color's alpha is not used.
|
||||
Color getDarkColor() {
|
||||
final color = _bindings.spine_slot_data_get_dark_color(_data);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setDarkColor(double r, double g, double b, double a) {
|
||||
@ -1211,8 +1234,12 @@ class Slot {
|
||||
/// color tinting.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_slot_get_color(_slot);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(Color color) {
|
||||
@ -1223,8 +1250,12 @@ class Slot {
|
||||
/// color's alpha is not used.
|
||||
Color getDarkColor() {
|
||||
final color = _bindings.spine_slot_get_dark_color(_slot);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setDarkColor(Color color) {
|
||||
@ -1574,8 +1605,12 @@ class RegionAttachment extends Attachment<spine_region_attachment> {
|
||||
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_region_attachment_get_color(_attachment);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -1662,7 +1697,9 @@ class VertexAttachment<T extends Pointer> extends Attachment<T> {
|
||||
|
||||
void setTimelineAttachment(Attachment? attachment) {
|
||||
_bindings.spine_vertex_attachment_set_timeline_attachment(
|
||||
_attachment.cast(), attachment == null ? nullptr : attachment._attachment.cast());
|
||||
_attachment.cast(),
|
||||
attachment == null ? nullptr : attachment._attachment.cast(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1713,8 +1750,12 @@ class MeshAttachment extends VertexAttachment<spine_mesh_attachment> {
|
||||
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_mesh_attachment_get_color(_attachment);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -1798,8 +1839,12 @@ class ClippingAttachment extends VertexAttachment<spine_clipping_attachment> {
|
||||
/// attachments are not usually rendered at runtime.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_clipping_attachment_get_color(_attachment);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -1819,8 +1864,12 @@ class BoundingBoxAttachment extends VertexAttachment<spine_bounding_box_attachme
|
||||
/// are not usually rendered at runtime.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_bounding_box_attachment_get_color(_attachment);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -1864,8 +1913,12 @@ class PathAttachment extends VertexAttachment<spine_path_attachment> {
|
||||
/// rendered at runtime.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_path_attachment_get_color(_attachment);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -1919,8 +1972,12 @@ class PointAttachment extends Attachment<spine_point_attachment> {
|
||||
/// attachments are not usually rendered at runtime.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_point_attachment_get_color(_attachment);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(double r, double g, double b, double a) {
|
||||
@ -1968,7 +2025,12 @@ class Skin {
|
||||
/// Adds an attachment to the skin for the specified slot index and name.
|
||||
void setAttachment(int slotIndex, String name, Attachment? attachment) {
|
||||
final nativeName = name.toNativeUtf8(allocator: _allocator);
|
||||
_bindings.spine_skin_set_attachment(_skin, slotIndex, nativeName.cast(), attachment == null ? nullptr : attachment._attachment.cast());
|
||||
_bindings.spine_skin_set_attachment(
|
||||
_skin,
|
||||
slotIndex,
|
||||
nativeName.cast(),
|
||||
attachment == null ? nullptr : attachment._attachment.cast(),
|
||||
);
|
||||
_allocator.free(nativeName);
|
||||
}
|
||||
|
||||
@ -2007,12 +2069,15 @@ class Skin {
|
||||
for (int i = 0; i < numEntries; i++) {
|
||||
final entry = _bindings.spine_skin_entries_get_entry(entries, i);
|
||||
Pointer<Utf8> name = _bindings.spine_skin_entry_get_name(entry).cast();
|
||||
result.add(SkinEntry(
|
||||
result.add(
|
||||
SkinEntry(
|
||||
_bindings.spine_skin_entry_get_slot_index(entry),
|
||||
name.toDartString(),
|
||||
_bindings.spine_skin_entry_get_attachment(entry).address == nullptr.address
|
||||
? null
|
||||
: Attachment._toSubclass(_bindings.spine_skin_entry_get_attachment(entry))));
|
||||
: Attachment._toSubclass(_bindings.spine_skin_entry_get_attachment(entry)),
|
||||
),
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -2836,7 +2901,11 @@ class Skeleton {
|
||||
Attachment? getAttachmentByName(String slotName, String attachmentName) {
|
||||
final slotNameNative = slotName.toNativeUtf8(allocator: _allocator);
|
||||
final attachmentNameNative = attachmentName.toNativeUtf8(allocator: _allocator);
|
||||
final attachment = _bindings.spine_skeleton_get_attachment_by_name(_skeleton, slotNameNative.cast(), attachmentNameNative.cast());
|
||||
final attachment = _bindings.spine_skeleton_get_attachment_by_name(
|
||||
_skeleton,
|
||||
slotNameNative.cast(),
|
||||
attachmentNameNative.cast(),
|
||||
);
|
||||
_allocator.free(slotNameNative);
|
||||
_allocator.free(attachmentNameNative);
|
||||
if (attachment.address == nullptr.address) return null;
|
||||
@ -2898,8 +2967,12 @@ class Skeleton {
|
||||
/// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
||||
Bounds getBounds() {
|
||||
final nativeBounds = _bindings.spine_skeleton_get_bounds(_skeleton);
|
||||
final bounds = Bounds(_bindings.spine_bounds_get_x(nativeBounds), _bindings.spine_bounds_get_y(nativeBounds),
|
||||
_bindings.spine_bounds_get_width(nativeBounds), _bindings.spine_bounds_get_height(nativeBounds));
|
||||
final bounds = Bounds(
|
||||
_bindings.spine_bounds_get_x(nativeBounds),
|
||||
_bindings.spine_bounds_get_y(nativeBounds),
|
||||
_bindings.spine_bounds_get_width(nativeBounds),
|
||||
_bindings.spine_bounds_get_height(nativeBounds),
|
||||
);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@ -2993,8 +3066,12 @@ class Skeleton {
|
||||
/// The color to tint all the skeleton's attachments.
|
||||
Color getColor() {
|
||||
final color = _bindings.spine_skeleton_get_color(_skeleton);
|
||||
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), _bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color));
|
||||
return Color(
|
||||
_bindings.spine_color_get_r(color),
|
||||
_bindings.spine_color_get_g(color),
|
||||
_bindings.spine_color_get_b(color),
|
||||
_bindings.spine_color_get_a(color),
|
||||
);
|
||||
}
|
||||
|
||||
void setColor(Color color) {
|
||||
@ -3508,7 +3585,7 @@ enum EventType {
|
||||
///
|
||||
/// Because this event is triggered at the end of [AnimationState.apply], any animations set in response to
|
||||
/// the event won't be applied until the next time the [AnimationState] is applied.
|
||||
event
|
||||
event,
|
||||
}
|
||||
|
||||
/// Stores the setup pose values for an [Event].
|
||||
@ -3801,7 +3878,12 @@ class AnimationState {
|
||||
/// See [setAnimation].
|
||||
TrackEntry setAnimationByName(int trackIndex, String animationName, bool loop) {
|
||||
final animation = animationName.toNativeUtf8(allocator: _allocator);
|
||||
final entry = _bindings.spine_animation_state_set_animation_by_name(_state, trackIndex, animation.cast(), loop ? -1 : 0);
|
||||
final entry = _bindings.spine_animation_state_set_animation_by_name(
|
||||
_state,
|
||||
trackIndex,
|
||||
animation.cast(),
|
||||
loop ? -1 : 0,
|
||||
);
|
||||
_allocator.free(animation);
|
||||
if (entry.address == nullptr.address) throw Exception("Couldn't set animation $animationName");
|
||||
return TrackEntry._(entry, this);
|
||||
@ -3816,7 +3898,12 @@ class AnimationState {
|
||||
/// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept
|
||||
/// after the [EventType.dispose] event occurs.
|
||||
TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) {
|
||||
final entry = _bindings.spine_animation_state_set_animation(_state, trackIndex, animation._animation, loop ? -1 : 0);
|
||||
final entry = _bindings.spine_animation_state_set_animation(
|
||||
_state,
|
||||
trackIndex,
|
||||
animation._animation,
|
||||
loop ? -1 : 0,
|
||||
);
|
||||
if (entry.address == nullptr.address) throw Exception("Couldn't set animation ${animation.getName()}");
|
||||
return TrackEntry._(entry, this);
|
||||
}
|
||||
@ -3826,7 +3913,13 @@ class AnimationState {
|
||||
/// See [addAnimation].
|
||||
TrackEntry addAnimationByName(int trackIndex, String animationName, bool loop, double delay) {
|
||||
final animation = animationName.toNativeUtf8(allocator: _allocator);
|
||||
final entry = _bindings.spine_animation_state_add_animation_by_name(_state, trackIndex, animation.cast(), loop ? -1 : 0, delay);
|
||||
final entry = _bindings.spine_animation_state_add_animation_by_name(
|
||||
_state,
|
||||
trackIndex,
|
||||
animation.cast(),
|
||||
loop ? -1 : 0,
|
||||
delay,
|
||||
);
|
||||
_allocator.free(animation);
|
||||
if (entry.address == nullptr.address) throw Exception("Couldn't add animation $animationName");
|
||||
return TrackEntry._(entry, this);
|
||||
@ -3843,7 +3936,13 @@ class AnimationState {
|
||||
/// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept
|
||||
/// after the [EventType.dispose] event occurs.
|
||||
TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, double delay) {
|
||||
final entry = _bindings.spine_animation_state_add_animation(_state, trackIndex, animation._animation, loop ? -1 : 0, delay);
|
||||
final entry = _bindings.spine_animation_state_add_animation(
|
||||
_state,
|
||||
trackIndex,
|
||||
animation._animation,
|
||||
loop ? -1 : 0,
|
||||
delay,
|
||||
);
|
||||
if (entry.address == nullptr.address) throw Exception("Couldn't add animation ${animation.getName()}");
|
||||
return TrackEntry._(entry, this);
|
||||
}
|
||||
@ -3966,8 +4065,10 @@ class SkeletonDrawable {
|
||||
_drawable = _bindings.spine_skeleton_drawable_create(skeletonData._data);
|
||||
skeleton = Skeleton._(_bindings.spine_skeleton_drawable_get_skeleton(_drawable));
|
||||
animationStateData = AnimationStateData._(_bindings.spine_skeleton_drawable_get_animation_state_data(_drawable));
|
||||
animationState = AnimationState._(_bindings.spine_skeleton_drawable_get_animation_state(_drawable),
|
||||
_bindings.spine_skeleton_drawable_get_animation_state_events(_drawable));
|
||||
animationState = AnimationState._(
|
||||
_bindings.spine_skeleton_drawable_get_animation_state(_drawable),
|
||||
_bindings.spine_skeleton_drawable_get_animation_state_events(_drawable),
|
||||
);
|
||||
skeleton.updateWorldTransform(Physics.none);
|
||||
}
|
||||
|
||||
@ -4030,7 +4131,11 @@ class SkeletonDrawable {
|
||||
List<RenderCommand> renderToCanvas(Canvas canvas) {
|
||||
var commands = render();
|
||||
for (final cmd in commands) {
|
||||
canvas.drawVertices(cmd.vertices, rendering.BlendMode.modulate, atlas.atlasPagePaints[cmd.atlasPageIndex][cmd.blendMode]!);
|
||||
canvas.drawVertices(
|
||||
cmd.vertices,
|
||||
rendering.BlendMode.modulate,
|
||||
atlas.atlasPagePaints[cmd.atlasPageIndex][cmd.blendMode]!,
|
||||
);
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
@ -4070,10 +4175,10 @@ class SkeletonDrawable {
|
||||
/// Scales and centers the skeleton to fit the within the bounds of [width] and [height].
|
||||
Future<RawImageData> renderToRawImageData(double width, double height, int bgColor) async {
|
||||
final recorder = renderToPictureRecorder(width, height, bgColor);
|
||||
var rawImageData =
|
||||
(await (await recorder.endRecording().toImage(width.toInt(), height.toInt())).toByteData(format: ImageByteFormat.rawRgba))!
|
||||
.buffer
|
||||
.asUint8List();
|
||||
var rawImageData = (await (await recorder.endRecording().toImage(
|
||||
width.toInt(),
|
||||
height.toInt(),
|
||||
)).toByteData(format: ImageByteFormat.rawRgba))!.buffer.asUint8List();
|
||||
return RawImageData(rawImageData, width.toInt(), height.toInt());
|
||||
}
|
||||
|
||||
@ -4135,7 +4240,13 @@ class RenderCommand {
|
||||
if (colors.isNotEmpty && colors[0] == -1) {
|
||||
vertices = Vertices.raw(VertexMode.triangles, positions, textureCoordinates: uvs, indices: indices);
|
||||
} else {
|
||||
vertices = Vertices.raw(VertexMode.triangles, positions, textureCoordinates: uvs, colors: colors, indices: indices);
|
||||
vertices = Vertices.raw(
|
||||
VertexMode.triangles,
|
||||
positions,
|
||||
textureCoordinates: uvs,
|
||||
colors: colors,
|
||||
indices: indices,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// On the web, rendering is done through CanvasKit, which requires copies of the native data.
|
||||
@ -4143,7 +4254,13 @@ class RenderCommand {
|
||||
final uvsCopy = Float32List.fromList(uvs);
|
||||
final colorsCopy = Int32List.fromList(colors);
|
||||
final indicesCopy = Uint16List.fromList(indices);
|
||||
vertices = Vertices.raw(VertexMode.triangles, positionsCopy, textureCoordinates: uvsCopy, colors: colorsCopy, indices: indicesCopy);
|
||||
vertices = Vertices.raw(
|
||||
VertexMode.triangles,
|
||||
positionsCopy,
|
||||
textureCoordinates: uvsCopy,
|
||||
colors: colorsCopy,
|
||||
indices: indicesCopy,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4158,7 +4275,10 @@ class DebugRenderer {
|
||||
..color = material.Colors.blue
|
||||
..style = PaintingStyle.fill;
|
||||
for (final bone in drawable.skeleton.getBones()) {
|
||||
canvas.drawRect(Rect.fromCenter(center: Offset(bone.getWorldX(), bone.getWorldY()), width: 5, height: 5), bonePaint);
|
||||
canvas.drawRect(
|
||||
Rect.fromCenter(center: Offset(bone.getWorldX(), bone.getWorldY()), width: 5, height: 5),
|
||||
bonePaint,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -74,8 +74,13 @@ class SpineWidgetController {
|
||||
|
||||
/// Constructs a new [SpineWidget] controller. See the class documentation of [SpineWidgetController] for information on
|
||||
/// the optional arguments.
|
||||
SpineWidgetController(
|
||||
{this.onInitialized, this.onBeforeUpdateWorldTransforms, this.onAfterUpdateWorldTransforms, this.onBeforePaint, this.onAfterPaint});
|
||||
SpineWidgetController({
|
||||
this.onInitialized,
|
||||
this.onBeforeUpdateWorldTransforms,
|
||||
this.onAfterUpdateWorldTransforms,
|
||||
this.onBeforePaint,
|
||||
this.onAfterPaint,
|
||||
});
|
||||
|
||||
void _initialize(SkeletonDrawable drawable) {
|
||||
var wasInitialized = _drawable != null;
|
||||
@ -203,7 +208,7 @@ class SkinAndAnimationBounds extends BoundsProvider {
|
||||
/// The [stepTime], given in seconds, defines at what interval the bounds should be sampled
|
||||
/// across the entire animation.
|
||||
SkinAndAnimationBounds({List<String>? skins, this.animation, this.stepTime = 0.1})
|
||||
: skins = skins == null || skins.isEmpty ? ["default"] : skins;
|
||||
: skins = skins == null || skins.isEmpty ? ["default"] : skins;
|
||||
|
||||
@override
|
||||
Bounds computeBounds(SkeletonDrawable drawable) {
|
||||
@ -282,15 +287,23 @@ class SpineWidget extends StatefulWidget {
|
||||
/// are used.
|
||||
///
|
||||
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
|
||||
SpineWidget.fromAsset(this._atlasFile, this._skeletonFile, this._controller,
|
||||
{AssetBundle? bundle, BoxFit? fit, Alignment? alignment, BoundsProvider? boundsProvider, bool? sizedByBounds, super.key})
|
||||
: _assetType = _AssetType.asset,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_drawable = null,
|
||||
_bundle = bundle ?? rootBundle;
|
||||
SpineWidget.fromAsset(
|
||||
this._atlasFile,
|
||||
this._skeletonFile,
|
||||
this._controller, {
|
||||
AssetBundle? bundle,
|
||||
BoxFit? fit,
|
||||
Alignment? alignment,
|
||||
BoundsProvider? boundsProvider,
|
||||
bool? sizedByBounds,
|
||||
super.key,
|
||||
}) : _assetType = _AssetType.asset,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_drawable = null,
|
||||
_bundle = bundle ?? rootBundle;
|
||||
|
||||
/// Constructs a new [SpineWidget] from files. The [_atlasFile] specifies the `.atlas` file to be loaded for the images used to render
|
||||
/// the skeleton. The [_skeletonFile] specifies either a Skeleton `.json` or `.skel` file containing the skeleton data.
|
||||
@ -303,15 +316,22 @@ class SpineWidget extends StatefulWidget {
|
||||
/// are used.
|
||||
///
|
||||
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
|
||||
const SpineWidget.fromFile(this._atlasFile, this._skeletonFile, this._controller,
|
||||
{BoxFit? fit, Alignment? alignment, BoundsProvider? boundsProvider, bool? sizedByBounds, super.key})
|
||||
: _assetType = _AssetType.file,
|
||||
_bundle = null,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_drawable = null;
|
||||
const SpineWidget.fromFile(
|
||||
this._atlasFile,
|
||||
this._skeletonFile,
|
||||
this._controller, {
|
||||
BoxFit? fit,
|
||||
Alignment? alignment,
|
||||
BoundsProvider? boundsProvider,
|
||||
bool? sizedByBounds,
|
||||
super.key,
|
||||
}) : _assetType = _AssetType.file,
|
||||
_bundle = null,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_drawable = null;
|
||||
|
||||
/// Constructs a new [SpineWidget] from HTTP URLs. The [_atlasFile] specifies the `.atlas` file to be loaded for the images used to render
|
||||
/// the skeleton. The [_skeletonFile] specifies either a Skeleton `.json` or `.skel` file containing the skeleton data.
|
||||
@ -324,15 +344,22 @@ class SpineWidget extends StatefulWidget {
|
||||
/// are used.
|
||||
///
|
||||
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
|
||||
const SpineWidget.fromHttp(this._atlasFile, this._skeletonFile, this._controller,
|
||||
{BoxFit? fit, Alignment? alignment, BoundsProvider? boundsProvider, bool? sizedByBounds, super.key})
|
||||
: _assetType = _AssetType.http,
|
||||
_bundle = null,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_drawable = null;
|
||||
const SpineWidget.fromHttp(
|
||||
this._atlasFile,
|
||||
this._skeletonFile,
|
||||
this._controller, {
|
||||
BoxFit? fit,
|
||||
Alignment? alignment,
|
||||
BoundsProvider? boundsProvider,
|
||||
bool? sizedByBounds,
|
||||
super.key,
|
||||
}) : _assetType = _AssetType.http,
|
||||
_bundle = null,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_drawable = null;
|
||||
|
||||
/// Constructs a new [SpineWidget] from a [SkeletonDrawable].
|
||||
///
|
||||
@ -344,16 +371,22 @@ class SpineWidget extends StatefulWidget {
|
||||
/// are used.
|
||||
///
|
||||
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
|
||||
const SpineWidget.fromDrawable(this._drawable, this._controller,
|
||||
{BoxFit? fit, Alignment? alignment, BoundsProvider? boundsProvider, bool? sizedByBounds, super.key})
|
||||
: _assetType = _AssetType.drawable,
|
||||
_bundle = null,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_skeletonFile = null,
|
||||
_atlasFile = null;
|
||||
const SpineWidget.fromDrawable(
|
||||
this._drawable,
|
||||
this._controller, {
|
||||
BoxFit? fit,
|
||||
Alignment? alignment,
|
||||
BoundsProvider? boundsProvider,
|
||||
bool? sizedByBounds,
|
||||
super.key,
|
||||
}) : _assetType = _AssetType.drawable,
|
||||
_bundle = null,
|
||||
_fit = fit ?? BoxFit.contain,
|
||||
_alignment = alignment ?? Alignment.center,
|
||||
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
|
||||
_sizedByBounds = sizedByBounds ?? false,
|
||||
_skeletonFile = null,
|
||||
_atlasFile = null;
|
||||
|
||||
@override
|
||||
State<SpineWidget> createState() => _SpineWidgetState();
|
||||
@ -382,8 +415,7 @@ class _SpineWidgetState extends State<SpineWidget> {
|
||||
// loaded.
|
||||
bool hasChanged = true;
|
||||
if (oldWidget._assetType == widget._assetType) {
|
||||
if (oldWidget._assetType == _AssetType.drawable &&
|
||||
oldWidget._drawable == widget._drawable) {
|
||||
if (oldWidget._assetType == _AssetType.drawable && oldWidget._drawable == widget._drawable) {
|
||||
hasChanged = false;
|
||||
} else if (oldWidget._skeletonFile == widget._skeletonFile &&
|
||||
oldWidget._atlasFile == widget._atlasFile &&
|
||||
@ -431,7 +463,13 @@ class _SpineWidgetState extends State<SpineWidget> {
|
||||
Widget build(BuildContext context) {
|
||||
if (_drawable != null) {
|
||||
return _SpineRenderObjectWidget(
|
||||
_drawable!, widget._controller, widget._fit, widget._alignment, _computedBounds, widget._sizedByBounds);
|
||||
_drawable!,
|
||||
widget._controller,
|
||||
widget._fit,
|
||||
widget._alignment,
|
||||
_computedBounds,
|
||||
widget._sizedByBounds,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
@ -452,7 +490,14 @@ class _SpineRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
final Bounds _bounds;
|
||||
final bool _sizedByBounds;
|
||||
|
||||
const _SpineRenderObjectWidget(this._skeletonDrawable, this._controller, this._fit, this._alignment, this._bounds, this._sizedByBounds);
|
||||
const _SpineRenderObjectWidget(
|
||||
this._skeletonDrawable,
|
||||
this._controller,
|
||||
this._fit,
|
||||
this._alignment,
|
||||
this._bounds,
|
||||
this._sizedByBounds,
|
||||
);
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
@ -481,7 +526,14 @@ class _SpineRenderObject extends RenderBox {
|
||||
bool _disposed = false;
|
||||
bool _firstUpdated = false;
|
||||
|
||||
_SpineRenderObject(this._skeletonDrawable, this._controller, this._fit, this._alignment, this._bounds, this._sizedByBounds);
|
||||
_SpineRenderObject(
|
||||
this._skeletonDrawable,
|
||||
this._controller,
|
||||
this._fit,
|
||||
this._alignment,
|
||||
this._bounds,
|
||||
this._sizedByBounds,
|
||||
);
|
||||
|
||||
set skeletonDrawable(SkeletonDrawable skeletonDrawable) {
|
||||
if (_skeletonDrawable == skeletonDrawable) return;
|
||||
|
||||
41
spine-glfw/CMakePresets.json
Normal file
41
spine-glfw/CMakePresets.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 20,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "debug",
|
||||
"displayName": "Debug",
|
||||
"description": "Debug build with compile commands",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "release",
|
||||
"displayName": "Release",
|
||||
"description": "Release build",
|
||||
"inherits": "debug",
|
||||
"binaryDir": "${sourceDir}/build/release",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "debug",
|
||||
"configurePreset": "debug"
|
||||
},
|
||||
{
|
||||
"name": "release",
|
||||
"configurePreset": "release"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package;
|
||||
|
||||
@ -35,63 +35,61 @@ import starlingExamples.Scene.SceneManager;
|
||||
import starling.core.Starling;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxGame;
|
||||
|
||||
import openfl.display.Sprite;
|
||||
import openfl.text.TextField;
|
||||
import openfl.text.TextFormat;
|
||||
import openfl.events.MouseEvent;
|
||||
|
||||
import openfl.geom.Rectangle;
|
||||
import starling.events.Event;
|
||||
|
||||
class Main extends Sprite {
|
||||
private var background:Sprite;
|
||||
private var background:Sprite;
|
||||
private var flixelButton:Sprite;
|
||||
private var starlingButton:Sprite;
|
||||
private var starlingButton:Sprite;
|
||||
private var uiContainer:Sprite;
|
||||
|
||||
private static inline var ratio = 4;
|
||||
private static inline var STAGE_WIDTH:Int = 100 * ratio;
|
||||
private static inline var STAGE_HEIGHT:Int = 200 * ratio;
|
||||
private static inline var BUTTON_WIDTH:Int = 80 * ratio;
|
||||
private static inline var BUTTON_HEIGHT:Int = 40 * ratio;
|
||||
private static inline var BUTTON_SPACING:Int = 20 * ratio;
|
||||
private static inline var STAGE_WIDTH:Int = 100 * ratio;
|
||||
private static inline var STAGE_HEIGHT:Int = 200 * ratio;
|
||||
private static inline var BUTTON_WIDTH:Int = 80 * ratio;
|
||||
private static inline var BUTTON_HEIGHT:Int = 40 * ratio;
|
||||
private static inline var BUTTON_SPACING:Int = 20 * ratio;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
|
||||
}
|
||||
public function new() {
|
||||
super();
|
||||
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
|
||||
}
|
||||
|
||||
private function onAddedToStage(e:Event):Void {
|
||||
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
|
||||
createUI();
|
||||
centerUI();
|
||||
stage.addEventListener(Event.RESIZE, onResize);
|
||||
}
|
||||
private function onAddedToStage(e:Event):Void {
|
||||
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
|
||||
createUI();
|
||||
centerUI();
|
||||
stage.addEventListener(Event.RESIZE, onResize);
|
||||
}
|
||||
|
||||
private function createUI():Void {
|
||||
uiContainer = new Sprite();
|
||||
addChild(uiContainer);
|
||||
private function createUI():Void {
|
||||
uiContainer = new Sprite();
|
||||
addChild(uiContainer);
|
||||
|
||||
background = new Sprite();
|
||||
background.graphics.beginFill(0xA2A2A2);
|
||||
background.graphics.drawRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
|
||||
background.graphics.endFill();
|
||||
uiContainer.addChild(background);
|
||||
background = new Sprite();
|
||||
background.graphics.beginFill(0xA2A2A2);
|
||||
background.graphics.drawRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
|
||||
background.graphics.endFill();
|
||||
uiContainer.addChild(background);
|
||||
|
||||
flixelButton = createButton("Flixel", 0xFF0000);
|
||||
uiContainer.addChild(flixelButton);
|
||||
flixelButton = createButton("Flixel", 0xFF0000);
|
||||
uiContainer.addChild(flixelButton);
|
||||
|
||||
starlingButton = createButton("Starling", 0x00FF00);
|
||||
uiContainer.addChild(starlingButton);
|
||||
starlingButton = createButton("Starling", 0x00FF00);
|
||||
uiContainer.addChild(starlingButton);
|
||||
|
||||
positionButtons();
|
||||
positionButtons();
|
||||
|
||||
flixelButton.addEventListener(MouseEvent.CLICK, onFlixelClick);
|
||||
starlingButton.addEventListener(MouseEvent.CLICK, onStarlingClick);
|
||||
}
|
||||
flixelButton.addEventListener(MouseEvent.CLICK, onFlixelClick);
|
||||
starlingButton.addEventListener(MouseEvent.CLICK, onStarlingClick);
|
||||
}
|
||||
|
||||
private function createButton(label:String, color:Int):Sprite {
|
||||
private function createButton(label:String, color:Int):Sprite {
|
||||
var button = new Sprite();
|
||||
var g = button.graphics;
|
||||
|
||||
@ -116,53 +114,54 @@ class Main extends Sprite {
|
||||
return button;
|
||||
}
|
||||
|
||||
private function positionButtons():Void {
|
||||
var totalHeight = (BUTTON_HEIGHT * 2) + BUTTON_SPACING;
|
||||
var startY = (STAGE_HEIGHT - totalHeight) / 2;
|
||||
private function positionButtons():Void {
|
||||
var totalHeight = (BUTTON_HEIGHT * 2) + BUTTON_SPACING;
|
||||
var startY = (STAGE_HEIGHT - totalHeight) / 2;
|
||||
|
||||
flixelButton.x = (STAGE_WIDTH - BUTTON_WIDTH) / 2;
|
||||
flixelButton.y = startY + BUTTON_HEIGHT + BUTTON_SPACING;
|
||||
flixelButton.x = (STAGE_WIDTH - BUTTON_WIDTH) / 2;
|
||||
flixelButton.y = startY + BUTTON_HEIGHT + BUTTON_SPACING;
|
||||
|
||||
starlingButton.x = (STAGE_WIDTH - BUTTON_WIDTH) / 2;
|
||||
starlingButton.y = startY;
|
||||
}
|
||||
starlingButton.x = (STAGE_WIDTH - BUTTON_WIDTH) / 2;
|
||||
starlingButton.y = startY;
|
||||
}
|
||||
|
||||
private function centerUI():Void {
|
||||
uiContainer.x = (stage.stageWidth - STAGE_WIDTH) / 2;
|
||||
uiContainer.y = (stage.stageHeight - STAGE_HEIGHT) / 2;
|
||||
}
|
||||
uiContainer.x = (stage.stageWidth - STAGE_WIDTH) / 2;
|
||||
uiContainer.y = (stage.stageHeight - STAGE_HEIGHT) / 2;
|
||||
}
|
||||
|
||||
private function onResize(e:Event):Void {
|
||||
centerUI();
|
||||
}
|
||||
private function onResize(e:Event):Void {
|
||||
centerUI();
|
||||
}
|
||||
|
||||
private function onFlixelClick(e:MouseEvent):Void {
|
||||
trace("Launching Flixel game");
|
||||
private function onFlixelClick(e:MouseEvent):Void {
|
||||
trace("Launching Flixel game");
|
||||
destroyUI();
|
||||
addChild(new FlxGame(640, 480, FlixelState));
|
||||
FlxG.autoPause = false;
|
||||
}
|
||||
}
|
||||
|
||||
private function destroyUI():Void {
|
||||
flixelButton.removeEventListener(MouseEvent.CLICK, onFlixelClick);
|
||||
starlingButton.removeEventListener(MouseEvent.CLICK, onStarlingClick);
|
||||
stage.removeEventListener(Event.RESIZE, onResize);
|
||||
flixelButton.removeEventListener(MouseEvent.CLICK, onFlixelClick);
|
||||
starlingButton.removeEventListener(MouseEvent.CLICK, onStarlingClick);
|
||||
stage.removeEventListener(Event.RESIZE, onResize);
|
||||
|
||||
removeChild(uiContainer);
|
||||
removeChild(uiContainer);
|
||||
|
||||
background = null;
|
||||
flixelButton = null;
|
||||
starlingButton = null;
|
||||
uiContainer = null;
|
||||
}
|
||||
background = null;
|
||||
flixelButton = null;
|
||||
starlingButton = null;
|
||||
uiContainer = null;
|
||||
}
|
||||
|
||||
private var starlingSingleton:Starling;
|
||||
private function onStarlingClick(e:MouseEvent):Void {
|
||||
trace("Launching Starling game");
|
||||
|
||||
private function onStarlingClick(e:MouseEvent):Void {
|
||||
trace("Launching Starling game");
|
||||
starlingSingleton = new Starling(starling.display.Sprite, stage, new Rectangle(0, 0, 800, 600));
|
||||
starlingSingleton.supportHighResolutions = true;
|
||||
starlingSingleton.addEventListener(Event.ROOT_CREATED, onStarlingRootCreated);
|
||||
}
|
||||
}
|
||||
|
||||
private function onStarlingRootCreated(event:Event):Void {
|
||||
destroyUI();
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package;
|
||||
|
||||
@ -34,10 +34,8 @@ import flixel.FlxG;
|
||||
import flixel.FlxGame;
|
||||
import openfl.display.Sprite;
|
||||
|
||||
class MainFlixel extends Sprite
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
class MainFlixel extends Sprite {
|
||||
public function new() {
|
||||
super();
|
||||
addChild(new FlxGame(640, 480, FlixelState));
|
||||
FlxG.autoPause = false;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package;
|
||||
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.text.FlxText;
|
||||
import spine.Skin;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
@ -43,6 +43,7 @@ class BasicExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
@ -66,22 +67,20 @@ class BasicExample extends FlxState {
|
||||
trace("loaded");
|
||||
}
|
||||
|
||||
override public function update(elapsed:Float):Void
|
||||
{
|
||||
if (FlxG.keys.anyPressed([RIGHT])) {
|
||||
skeletonSprite.x += 15;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([LEFT])) {
|
||||
skeletonSprite.x -= 15;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([DOWN])) {
|
||||
skeletonSprite.y += 15;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([UP])) {
|
||||
skeletonSprite.y -= 15;
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
override public function update(elapsed:Float):Void {
|
||||
if (FlxG.keys.anyPressed([RIGHT])) {
|
||||
skeletonSprite.x += 15;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([LEFT])) {
|
||||
skeletonSprite.x -= 15;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([DOWN])) {
|
||||
skeletonSprite.y += 15;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([UP])) {
|
||||
skeletonSprite.y -= 15;
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import flixel.text.FlxText;
|
||||
import flixel.math.FlxPoint;
|
||||
import spine.Skin;
|
||||
@ -47,6 +46,7 @@ class CelestialCircusExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
@ -55,7 +55,8 @@ class CelestialCircusExample extends FlxState {
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/celestial-circus.atlas"), new FlixelTextureLoader("assets/celestial-circus.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/celestial-circus-pro.skel") : Assets.getText("assets/celestial-circus-pro.json"), atlas, .15);
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/celestial-circus-pro.skel") : Assets.getText("assets/celestial-circus-pro.json"),
|
||||
atlas, .15);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
@ -73,32 +74,27 @@ class CelestialCircusExample extends FlxState {
|
||||
var dragging:Bool = false;
|
||||
var lastX:Float = 0;
|
||||
var lastY:Float = 0;
|
||||
override public function update(elapsed:Float):Void
|
||||
{
|
||||
|
||||
override public function update(elapsed:Float):Void {
|
||||
super.update(elapsed);
|
||||
|
||||
mousePosition = FlxG.mouse.getPosition();
|
||||
|
||||
if (FlxG.mouse.justPressed && skeletonSprite.overlapsPoint(mousePosition))
|
||||
{
|
||||
if (FlxG.mouse.justPressed && skeletonSprite.overlapsPoint(mousePosition)) {
|
||||
dragging = true;
|
||||
lastX = mousePosition.x;
|
||||
lastY = mousePosition.y;
|
||||
lastY = mousePosition.y;
|
||||
}
|
||||
|
||||
if (FlxG.mouse.justReleased) dragging = false;
|
||||
if (FlxG.mouse.justReleased)
|
||||
dragging = false;
|
||||
|
||||
if (dragging)
|
||||
{
|
||||
if (dragging) {
|
||||
skeletonSprite.x += mousePosition.x - lastX;
|
||||
skeletonSprite.y += mousePosition.y - lastY;
|
||||
skeletonSprite.skeleton.physicsTranslate(
|
||||
mousePosition.x - lastX,
|
||||
mousePosition.y - lastY,
|
||||
);
|
||||
skeletonSprite.skeleton.physicsTranslate(mousePosition.x - lastX, mousePosition.y - lastY,);
|
||||
lastX = mousePosition.x;
|
||||
lastY = mousePosition.y;
|
||||
lastY = mousePosition.y;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import flixel.util.FlxSave;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.util.FlxColor;
|
||||
@ -49,7 +48,8 @@ class ControlBonesExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
private var controlBones = [];
|
||||
private var controls:Array<FlxSprite> = [];
|
||||
private var controls:Array<FlxSprite> = [];
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
@ -92,7 +92,7 @@ class ControlBonesExample extends FlxState {
|
||||
}
|
||||
|
||||
var point = [.0, .0];
|
||||
skeletonSprite.beforeUpdateWorldTransforms = function (go) {
|
||||
skeletonSprite.beforeUpdateWorldTransforms = function(go) {
|
||||
for (i in 0...controls.length) {
|
||||
var bone = controlBones[i];
|
||||
var control = controls[i];
|
||||
@ -101,7 +101,7 @@ class ControlBonesExample extends FlxState {
|
||||
go.haxeWorldCoordinatesToBone(point, bone);
|
||||
bone.pose.x = point[0];
|
||||
bone.pose.y = point[1];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
super.create();
|
||||
@ -111,25 +111,24 @@ class ControlBonesExample extends FlxState {
|
||||
var offsetX:Float = 0;
|
||||
var offsetY:Float = 0;
|
||||
var sprite:FlxSprite;
|
||||
override public function update(elapsed:Float):Void
|
||||
{
|
||||
|
||||
override public function update(elapsed:Float):Void {
|
||||
super.update(elapsed);
|
||||
|
||||
mousePosition = FlxG.mouse.getPosition();
|
||||
|
||||
for (control in controls) {
|
||||
if (FlxG.mouse.justPressed && control.overlapsPoint(mousePosition))
|
||||
{
|
||||
if (FlxG.mouse.justPressed && control.overlapsPoint(mousePosition)) {
|
||||
sprite = control;
|
||||
offsetX = mousePosition.x - sprite.x;
|
||||
offsetY = mousePosition.y - sprite.y;
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.mouse.justReleased) sprite = null;
|
||||
if (FlxG.mouse.justReleased)
|
||||
sprite = null;
|
||||
|
||||
if (sprite != null)
|
||||
{
|
||||
if (sprite != null) {
|
||||
sprite.x = mousePosition.x - offsetX;
|
||||
sprite.y = mousePosition.y - offsetY;
|
||||
}
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import flixel.text.FlxText;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
@ -76,9 +75,7 @@ class EventsExample extends FlxState {
|
||||
skeletonSprite.skeleton.setupPoseBones();
|
||||
add(skeletonSprite);
|
||||
|
||||
trackEntry.onEvent.add(
|
||||
(entry, event) -> log('Custom event for ${entry.animation.name}: ${event.data.name}'));
|
||||
|
||||
trackEntry.onEvent.add((entry, event) -> log('Custom event for ${entry.animation.name}: ${event.data.name}'));
|
||||
|
||||
add(textContainer);
|
||||
super.create();
|
||||
@ -88,6 +85,7 @@ class EventsExample extends FlxState {
|
||||
private var logs = new Array<FlxText>();
|
||||
private var logsNumber = 0;
|
||||
private var yOffset = 12;
|
||||
|
||||
private function log(text:String) {
|
||||
var length = logs.length;
|
||||
var newLog = new FlxText(250, 30, text);
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
@ -43,8 +43,7 @@ import flixel.FlxG;
|
||||
import flixel.FlxState;
|
||||
import flixel.text.FlxText;
|
||||
|
||||
class FlixelState extends FlxState
|
||||
{
|
||||
class FlixelState extends FlxState {
|
||||
var spineSprite:SkeletonSprite;
|
||||
var sprite:FlxSprite;
|
||||
var sprite2:FlxSprite;
|
||||
@ -57,8 +56,7 @@ class FlixelState extends FlxState
|
||||
var scale = 4;
|
||||
var speed:Float;
|
||||
|
||||
override public function create():Void
|
||||
{
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
// setting speed of spineboy (450 is the speed to not let him slide)
|
||||
@ -76,8 +74,8 @@ class FlixelState extends FlxState
|
||||
|
||||
// creating the text to display overlapping state
|
||||
myText = new FlxText(0, 25, 150, "", 16);
|
||||
myText.alignment = CENTER;
|
||||
group.add(myText);
|
||||
myText.alignment = CENTER;
|
||||
group.add(myText);
|
||||
|
||||
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new BasicExample()));
|
||||
button.setPosition(FlxG.width * .75, FlxG.height / 10);
|
||||
@ -92,14 +90,14 @@ class FlixelState extends FlxState
|
||||
// instructions
|
||||
var groupInstructions = new FlxSpriteGroup();
|
||||
groupInstructions.setPosition(50, 405);
|
||||
groupInstructions.add(new FlxText(0, 0, 200, "Left/Right - Move", 16));
|
||||
groupInstructions.add(new FlxText(0, 25, 150, "Space - Jump", 16));
|
||||
groupInstructions.add(new FlxText(200, 25, 400, "Click the button for the next example", 16));
|
||||
groupInstructions.add(new FlxText(0, 0, 200, "Left/Right - Move", 16));
|
||||
groupInstructions.add(new FlxText(0, 25, 150, "Space - Jump", 16));
|
||||
groupInstructions.add(new FlxText(200, 25, 400, "Click the button for the next example", 16));
|
||||
add(groupInstructions);
|
||||
|
||||
// loading spineboy
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/spineboy.atlas"), new FlixelTextureLoader("assets/spineboy.atlas"));
|
||||
var skeletondata = SkeletonData.from(Assets.getText("assets/spineboy-pro.json"), atlas, 1/scale);
|
||||
var skeletondata = SkeletonData.from(Assets.getText("assets/spineboy-pro.json"), atlas, 1 / scale);
|
||||
var animationStateData = new AnimationStateData(skeletondata);
|
||||
spineSprite = new SkeletonSprite(skeletondata, animationStateData);
|
||||
|
||||
@ -166,8 +164,8 @@ class FlixelState extends FlxState
|
||||
}
|
||||
|
||||
var justSetIdle = true;
|
||||
override public function update(elapsed:Float):Void
|
||||
{
|
||||
|
||||
override public function update(elapsed:Float):Void {
|
||||
if (FlxG.overlap(spineSprite, group)) {
|
||||
myText.text = "Overlapping";
|
||||
} else {
|
||||
@ -191,11 +189,13 @@ class FlixelState extends FlxState
|
||||
var flipped = false;
|
||||
var deltaX;
|
||||
if (FlxG.keys.anyPressed([RIGHT])) {
|
||||
if (spineSprite.flipX == true) flipped = true;
|
||||
if (spineSprite.flipX == true)
|
||||
flipped = true;
|
||||
spineSprite.flipX = false;
|
||||
}
|
||||
if (FlxG.keys.anyPressed([LEFT])) {
|
||||
if (spineSprite.flipX == false) flipped = true;
|
||||
if (spineSprite.flipX == false)
|
||||
flipped = true;
|
||||
spineSprite.flipX = true;
|
||||
}
|
||||
|
||||
@ -211,14 +211,12 @@ class FlixelState extends FlxState
|
||||
spineSprite.state.setAnimationByName(0, "walk", true);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (!jumping && !justSetIdle) {
|
||||
justSetWalking = false;
|
||||
justSetIdle = true;
|
||||
spineSprite.state.setAnimationByName(0, "idle", true);
|
||||
}
|
||||
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
@ -43,9 +42,10 @@ import spine.atlas.TextureAtlas;
|
||||
|
||||
class MixAndMatchExample extends FlxState {
|
||||
var loadBinary = false;
|
||||
// var loadBinary = true;
|
||||
|
||||
// var loadBinary = true;
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
@ -54,7 +54,8 @@ class MixAndMatchExample extends FlxState {
|
||||
add(button);
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/mix-and-match.atlas"), new FlixelTextureLoader("assets/mix-and-match.atlas"));
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/mix-and-match-pro.skel") : Assets.getText("assets/mix-and-match-pro.json"), atlas, .5);
|
||||
var data = SkeletonData.from(loadBinary ? Assets.getBytes("assets/mix-and-match-pro.skel") : Assets.getText("assets/mix-and-match-pro.json"), atlas,
|
||||
.5);
|
||||
var animationStateData = new AnimationStateData(data);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
@ -80,5 +81,4 @@ class MixAndMatchExample extends FlxState {
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
import spine.flixel.SkeletonSprite;
|
||||
@ -44,6 +43,7 @@ class SequenceExample extends FlxState {
|
||||
var loadBinary = true;
|
||||
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
|
||||
override public function create():Void {
|
||||
FlxG.cameras.bgColor = 0xffa1b2b0;
|
||||
|
||||
@ -64,5 +64,4 @@ class SequenceExample extends FlxState {
|
||||
add(skeletonSprite);
|
||||
super.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
|
||||
@ -25,11 +25,10 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package flixelExamples;
|
||||
|
||||
|
||||
import spine.Skin;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
@ -44,8 +44,9 @@ import starling.display.Quad;
|
||||
|
||||
class AnimationBoundExample extends Scene {
|
||||
var loadBinary = false;
|
||||
var skeletonSpriteClipping: SkeletonSprite;
|
||||
var skeletonSpriteNoClipping: SkeletonSprite;
|
||||
var skeletonSpriteClipping:SkeletonSprite;
|
||||
var skeletonSpriteNoClipping:SkeletonSprite;
|
||||
|
||||
public function load():Void {
|
||||
background.color = 0x333333;
|
||||
var scale = .2;
|
||||
@ -66,8 +67,8 @@ class AnimationBoundExample extends Scene {
|
||||
var animationClipping = skeletonSpriteClipping.state.setAnimationByName(0, "portal", true).animation;
|
||||
var animationBoundClipping = skeletonSpriteClipping.getAnimationBounds(animationClipping, true);
|
||||
var quad:Quad = new Quad(animationBoundClipping.width * scale, animationBoundClipping.height * scale, 0xc70000);
|
||||
quad.x = skeletonSpriteClipping.x + animationBoundClipping.x * scale;
|
||||
quad.y = skeletonSpriteClipping.y + animationBoundClipping.y * scale;
|
||||
quad.x = skeletonSpriteClipping.x + animationBoundClipping.x * scale;
|
||||
quad.y = skeletonSpriteClipping.y + animationBoundClipping.y * scale;
|
||||
|
||||
var animationStateDataNoClipping = new AnimationStateData(skeletondata);
|
||||
animationStateDataNoClipping.defaultMix = 0.25;
|
||||
@ -80,8 +81,8 @@ class AnimationBoundExample extends Scene {
|
||||
var animationNoClipping = skeletonSpriteNoClipping.state.setAnimationByName(0, "portal", true).animation;
|
||||
var animationBoundNoClipping = skeletonSpriteNoClipping.getAnimationBounds(animationNoClipping, false);
|
||||
var quadNoClipping:Quad = new Quad(animationBoundNoClipping.width * scale, animationBoundNoClipping.height * scale, 0xc70000);
|
||||
quadNoClipping.x = skeletonSpriteNoClipping.x + animationBoundNoClipping.x * scale;
|
||||
quadNoClipping.y = skeletonSpriteNoClipping.y + animationBoundNoClipping.y * scale;
|
||||
quadNoClipping.x = skeletonSpriteNoClipping.x + animationBoundNoClipping.x * scale;
|
||||
quadNoClipping.y = skeletonSpriteNoClipping.y + animationBoundNoClipping.y * scale;
|
||||
|
||||
addChild(quad);
|
||||
addChild(quadNoClipping);
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
@ -52,7 +52,8 @@ class CelestialCircusExample extends Scene {
|
||||
background.color = 0x333333;
|
||||
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/celestial-circus.atlas"), new StarlingTextureLoader("assets/celestial-circus.atlas"));
|
||||
var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/celestial-circus-pro.skel") : Assets.getText("assets/celestial-circus-pro.json"), atlas);
|
||||
var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/celestial-circus-pro.skel") : Assets.getText("assets/celestial-circus-pro.json"),
|
||||
atlas);
|
||||
|
||||
var animationStateData = new AnimationStateData(skeletondata);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
@ -83,10 +84,7 @@ class CelestialCircusExample extends Scene {
|
||||
skeletonTouch.getMovement(this, movement);
|
||||
skeletonSprite.x += movement.x;
|
||||
skeletonSprite.y += movement.y;
|
||||
skeletonSprite.skeleton.physicsTranslate(
|
||||
movement.x / skeletonSprite.scale,
|
||||
movement.y / skeletonSprite.scale,
|
||||
);
|
||||
skeletonSprite.skeleton.physicsTranslate(movement.x / skeletonSprite.scale, movement.y / skeletonSprite.scale,);
|
||||
}
|
||||
} else {
|
||||
var sceneTouch = e.getTouch(this);
|
||||
@ -94,8 +92,5 @@ class CelestialCircusExample extends Scene {
|
||||
SceneManager.getInstance().switchScene(new SnowglobeExample());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
@ -58,7 +58,6 @@ class CloudPotExample extends Scene {
|
||||
skeletonSprite.skeleton.updateWorldTransform(Physics.update);
|
||||
var bounds = skeletonSprite.skeleton.getBounds();
|
||||
|
||||
|
||||
skeletonSprite.scale = 0.2;
|
||||
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight / 2;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
@ -48,11 +48,12 @@ class ControlBonesExample extends Scene {
|
||||
var skeletonSprite:SkeletonSprite;
|
||||
private var movement = new openfl.geom.Point();
|
||||
private var controlBones = [];
|
||||
private var controls = [];
|
||||
private var controls = [];
|
||||
|
||||
public function load():Void {
|
||||
var atlas = new TextureAtlas(Assets.getText("assets/stretchyman.atlas"), new StarlingTextureLoader("assets/stretchyman.atlas"));
|
||||
var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/stretchyman-pro.skel") : Assets.getText("assets/stretchyman-pro.json"), atlas);
|
||||
var skeletondata = SkeletonData.from(loadBinary ? Assets.getBytes("assets/stretchyman-pro.skel") : Assets.getText("assets/stretchyman-pro.json"),
|
||||
atlas);
|
||||
var animationStateData = new AnimationStateData(skeletondata);
|
||||
animationStateData.defaultMix = 0.25;
|
||||
|
||||
@ -97,7 +98,7 @@ class ControlBonesExample extends Scene {
|
||||
}
|
||||
|
||||
var point = [.0, .0];
|
||||
skeletonSprite.beforeUpdateWorldTransforms = function (go) {
|
||||
skeletonSprite.beforeUpdateWorldTransforms = function(go) {
|
||||
for (i in 0...controls.length) {
|
||||
var bone = controlBones[i];
|
||||
var control = controls[i];
|
||||
@ -106,7 +107,7 @@ class ControlBonesExample extends Scene {
|
||||
go.haxeWorldCoordinatesToBone(point, bone);
|
||||
bone.pose.x = point[0];
|
||||
bone.pose.y = point[1];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
addEventListener(TouchEvent.TOUCH, onTouch);
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
@ -66,8 +66,7 @@ class EventsExample extends Scene {
|
||||
// add callback to the TrackEntry
|
||||
skeletonSprite.state.setAnimationByName(0, "walk", true);
|
||||
var trackEntry = skeletonSprite.state.addAnimationByName(0, "run", true, 3);
|
||||
trackEntry.onEvent.add(
|
||||
(entry, event) -> log('Custom event for ${entry.animation.name}: ${event.data.name}'));
|
||||
trackEntry.onEvent.add((entry, event) -> log('Custom event for ${entry.animation.name}: ${event.data.name}'));
|
||||
|
||||
addChild(skeletonSprite);
|
||||
juggler.add(skeletonSprite);
|
||||
@ -83,6 +82,7 @@ class EventsExample extends Scene {
|
||||
private var logs = new Array<TextField>();
|
||||
private var logsNumber = 0;
|
||||
private var yOffset = 12;
|
||||
|
||||
private function log(text:String) {
|
||||
var length = logs.length;
|
||||
var newLog = new TextField(250, 30, text);
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
@ -58,7 +58,7 @@ class SackExample extends Scene {
|
||||
|
||||
skeletonSprite.scale = 0.2;
|
||||
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight/ 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight / 2;
|
||||
|
||||
skeletonSprite.state.setAnimationByName(0, "cape-follow-example", true);
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
@ -57,10 +57,9 @@ class SnowglobeExample extends Scene {
|
||||
skeletonSprite.skeleton.updateWorldTransform(Physics.update);
|
||||
var bounds = skeletonSprite.skeleton.getBounds();
|
||||
|
||||
|
||||
skeletonSprite.scale = 0.15;
|
||||
skeletonSprite.x = Starling.current.stage.stageWidth / 2;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight/ 1.5;
|
||||
skeletonSprite.y = Starling.current.stage.stageHeight / 1.5;
|
||||
|
||||
skeletonSprite.state.setAnimationByName(0, "shake", true);
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package starlingExamples;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -37,7 +37,8 @@ package spine;
|
||||
class Bone extends PosedActive<BoneData, BoneLocal, BonePose> {
|
||||
static public var yDown:Bool = false;
|
||||
static public var yDir(get, never):Int;
|
||||
static private function get_yDir(): Int {
|
||||
|
||||
static private function get_yDir():Int {
|
||||
return Bone.yDown ? -1 : 1;
|
||||
}
|
||||
|
||||
@ -49,7 +50,7 @@ class Bone extends PosedActive<BoneData, BoneLocal, BonePose> {
|
||||
|
||||
public var sorted = false;
|
||||
|
||||
public function new (data:BoneData, parent:Bone) {
|
||||
public function new(data:BoneData, parent:Bone) {
|
||||
super(data, new BonePose(), new BonePose());
|
||||
this.parent = parent;
|
||||
applied.bone = this;
|
||||
|
||||
@ -25,13 +25,12 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
/** The setup pose for a bone. */
|
||||
class BoneData extends PosedData<BoneLocal> {
|
||||
|
||||
/** The index of the bone in spine.Skeleton.getBones(). */
|
||||
public final index:Int;
|
||||
|
||||
@ -41,6 +40,7 @@ class BoneData extends PosedData<BoneLocal> {
|
||||
public var length = 0.;
|
||||
|
||||
// Nonessential.
|
||||
|
||||
/** The color of the bone as it was in Spine, or a default color if nonessential data was not exported. Bones are not usually
|
||||
* rendered at runtime. */
|
||||
public var color = new Color(0, 0, 0, 0);
|
||||
@ -51,10 +51,12 @@ class BoneData extends PosedData<BoneLocal> {
|
||||
/** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */
|
||||
public var visible = false;
|
||||
|
||||
public function new (index:Int, name:String, parent:BoneData) {
|
||||
public function new(index:Int, name:String, parent:BoneData) {
|
||||
super(name, new BoneLocal());
|
||||
if (index < 0) throw new SpineException("index must be >= 0.");
|
||||
if (name == null) throw new SpineException("name cannot be null.");
|
||||
if (index < 0)
|
||||
throw new SpineException("index must be >= 0.");
|
||||
if (name == null)
|
||||
throw new SpineException("name cannot be null.");
|
||||
this.index = index;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@ -25,13 +25,12 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
/** Stores a bone's local pose. */
|
||||
class BoneLocal implements Pose<BoneLocal> {
|
||||
|
||||
/** The local x translation. */
|
||||
public var x:Float = 0;
|
||||
|
||||
@ -55,17 +54,19 @@ class BoneLocal implements Pose<BoneLocal> {
|
||||
|
||||
/** Determines how parent world transforms affect this bone. */
|
||||
public var inherit(default, set):Inherit;
|
||||
function set_inherit (value:Inherit):Inherit {
|
||||
if (value == null) throw new SpineException("inherit cannot be null.");
|
||||
|
||||
function set_inherit(value:Inherit):Inherit {
|
||||
if (value == null)
|
||||
throw new SpineException("inherit cannot be null.");
|
||||
inherit = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
public function new () {
|
||||
}
|
||||
public function new() {}
|
||||
|
||||
public function set (pose:BoneLocal):Void {
|
||||
if (pose == null) throw new SpineException("pose cannot be null.");
|
||||
public function set(pose:BoneLocal):Void {
|
||||
if (pose == null)
|
||||
throw new SpineException("pose cannot be null.");
|
||||
x = pose.x;
|
||||
y = pose.y;
|
||||
rotation = pose.rotation;
|
||||
@ -75,5 +76,4 @@ class BoneLocal implements Pose<BoneLocal> {
|
||||
shearY = pose.shearY;
|
||||
inherit = pose.inherit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,14 +25,13 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
/** The applied pose for a bone. This is the {@link Bone} pose with constraints applied and the world transform computed by
|
||||
* Skeleton.updateWorldTransform(Physics). */
|
||||
class BonePose extends BoneLocal implements Update {
|
||||
|
||||
public var bone:Bone;
|
||||
|
||||
/** Part of the world transform matrix for the X axis. If changed, updateAppliedTransform() should be called. */
|
||||
@ -61,14 +60,15 @@ class BonePose extends BoneLocal implements Update {
|
||||
// }
|
||||
|
||||
/** Called by Skeleton.updateCache() to compute the world transform, if needed. */
|
||||
public function update (skeleton:Skeleton, physics:Physics):Void {
|
||||
if (world != skeleton._update) updateWorldTransform(skeleton);
|
||||
public function update(skeleton:Skeleton, physics:Physics):Void {
|
||||
if (world != skeleton._update)
|
||||
updateWorldTransform(skeleton);
|
||||
}
|
||||
|
||||
/** Computes the world transform using the parent bone's applied pose and this pose. Child bones are not updated.
|
||||
*
|
||||
* @see https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine Runtimes Guide
|
||||
*/
|
||||
*
|
||||
* @see https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine Runtimes Guide
|
||||
*/
|
||||
public function updateWorldTransform(skeleton:Skeleton):Void {
|
||||
if (local == skeleton._update)
|
||||
updateLocalTransform(skeleton);
|
||||
@ -139,15 +139,19 @@ class BonePose extends BoneLocal implements Update {
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
case Inherit.noScale, Inherit.noScaleOrReflection:
|
||||
var r = rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);
|
||||
var r = rotation * MathUtils.degRad,
|
||||
cos = Math.cos(r),
|
||||
sin = Math.sin(r);
|
||||
var za = (pa * cos + pb * sin) / skeleton.scaleX;
|
||||
var zc = (pc * cos + pd * sin) / skeleton.scaleY;
|
||||
var s = Math.sqrt(za * za + zc * zc);
|
||||
if (s > 0.00001) s = 1 / s;
|
||||
if (s > 0.00001)
|
||||
s = 1 / s;
|
||||
za *= s;
|
||||
zc *= s;
|
||||
s = Math.sqrt(za * za + zc * zc);
|
||||
if (inherit == Inherit.noScale && ((pa * pd - pb * pc < 0) != ((skeleton.scaleX < 0) != (skeleton.scaleY < 0)))) s = -s;
|
||||
if (inherit == Inherit.noScale && ((pa * pd - pb * pc < 0) != ((skeleton.scaleX < 0) != (skeleton.scaleY < 0))))
|
||||
s = -s;
|
||||
r = Math.PI / 2 + Math.atan2(zc, za);
|
||||
var zb:Float = Math.cos(r) * s;
|
||||
var zd:Float = Math.sin(r) * s;
|
||||
@ -169,13 +173,13 @@ class BonePose extends BoneLocal implements Update {
|
||||
}
|
||||
|
||||
/** Computes the applied transform values from the world transform.
|
||||
*
|
||||
* If the world transform is modified (by a constraint, rotateWorld(), etc) then this method should be called so
|
||||
* the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply another
|
||||
* constraint).
|
||||
*
|
||||
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after
|
||||
* calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */
|
||||
*
|
||||
* If the world transform is modified (by a constraint, rotateWorld(), etc) then this method should be called so
|
||||
* the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply another
|
||||
* constraint).
|
||||
*
|
||||
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after
|
||||
* calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */
|
||||
public function updateLocalTransform(skeleton:Skeleton):Void {
|
||||
local = 0;
|
||||
world = skeleton._update;
|
||||
@ -215,15 +219,19 @@ class BonePose extends BoneLocal implements Update {
|
||||
ia = pd * pid;
|
||||
ib = pb * pid;
|
||||
case Inherit.noScale, Inherit.noScaleOrReflection:
|
||||
var r = rotation * MathUtils.degRad, cos = Math.cos(rotation), sin = Math.sin(rotation);
|
||||
var r = rotation * MathUtils.degRad,
|
||||
cos = Math.cos(rotation),
|
||||
sin = Math.sin(rotation);
|
||||
pa = (pa * cos + pb * sin) / skeleton.scaleX;
|
||||
pc = (pc * cos + pd * sin) / skeleton.scaleY;
|
||||
var s = Math.sqrt(pa * pa + pc * pc);
|
||||
if (s > 0.00001) s = 1 / s;
|
||||
if (s > 0.00001)
|
||||
s = 1 / s;
|
||||
pa *= s;
|
||||
pc *= s;
|
||||
s = Math.sqrt(pa * pa + pc * pc);
|
||||
if (inherit == Inherit.noScale && (pid < 0 != ((skeleton.scaleX < 0) != (skeleton.scaleY < 0)))) s = -s;
|
||||
if (inherit == Inherit.noScale && (pid < 0 != ((skeleton.scaleX < 0) != (skeleton.scaleY < 0))))
|
||||
s = -s;
|
||||
r = MathUtils.PI / 2 + Math.atan2(pc, pa);
|
||||
pb = Math.cos(r) * s;
|
||||
pd = Math.sin(r) * s;
|
||||
@ -255,24 +263,26 @@ class BonePose extends BoneLocal implements Update {
|
||||
}
|
||||
|
||||
/** If the world transform has been modified and the local transform no longer matches, {@link #updateLocalTransform(Skeleton)}
|
||||
* is called. */
|
||||
public function validateLocalTransform (skeleton: Skeleton) {
|
||||
if (local == skeleton._update) updateLocalTransform(skeleton);
|
||||
* is called. */
|
||||
public function validateLocalTransform(skeleton:Skeleton) {
|
||||
if (local == skeleton._update)
|
||||
updateLocalTransform(skeleton);
|
||||
}
|
||||
|
||||
public function modifyLocal (skeleton: Skeleton) {
|
||||
if (local == skeleton._update) updateLocalTransform(skeleton);
|
||||
public function modifyLocal(skeleton:Skeleton) {
|
||||
if (local == skeleton._update)
|
||||
updateLocalTransform(skeleton);
|
||||
world = 0;
|
||||
resetWorld(skeleton._update);
|
||||
}
|
||||
|
||||
public function modifyWorld (update:Int) {
|
||||
public function modifyWorld(update:Int) {
|
||||
local = update;
|
||||
world = update;
|
||||
resetWorld(update);
|
||||
}
|
||||
|
||||
public function resetWorld (update:Int) {
|
||||
public function resetWorld(update:Int) {
|
||||
var children = bone.children;
|
||||
for (i in 0...bone.children.length) {
|
||||
var child = children[i].applied;
|
||||
@ -331,14 +341,14 @@ class BonePose extends BoneLocal implements Update {
|
||||
}
|
||||
|
||||
/** Transforms a point from world coordinates to the parent bone's local coordinates. */
|
||||
public function worldToParent(world: Array<Float>):Array<Float> {
|
||||
public function worldToParent(world:Array<Float>):Array<Float> {
|
||||
if (world == null)
|
||||
throw new SpineException("world cannot be null.");
|
||||
return bone.parent == null ? world : bone.parent.applied.worldToLocal(world);
|
||||
}
|
||||
|
||||
/** Transforms a point from the parent bone's coordinates to world coordinates. */
|
||||
public function parentToWorld(world: Array<Float>):Array<Float> {
|
||||
public function parentToWorld(world:Array<Float>):Array<Float> {
|
||||
if (world == null)
|
||||
throw new SpineException("world cannot be null.");
|
||||
return bone.parent == null ? world : bone.parent.applied.localToWorld(world);
|
||||
@ -373,7 +383,7 @@ class BonePose extends BoneLocal implements Update {
|
||||
d = sin * rb + cos * d;
|
||||
}
|
||||
|
||||
public function toString ():String {
|
||||
public function toString():String {
|
||||
return bone.data.name;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -33,17 +33,16 @@ abstract class Constraint< //
|
||||
T:Constraint<T, D, P>, //
|
||||
D:ConstraintData<T, P>, //
|
||||
P:Pose<Any>> //
|
||||
extends PosedActive<D, P, P> implements Update {
|
||||
|
||||
public function new (data:D, pose:P, constrained:P) {
|
||||
extends PosedActive<D, P, P> implements Update {
|
||||
public function new(data:D, pose:P, constrained:P) {
|
||||
super(data, pose, constrained);
|
||||
}
|
||||
|
||||
public abstract function copy (skeleton:Skeleton):T;
|
||||
public abstract function copy(skeleton:Skeleton):T;
|
||||
|
||||
public abstract function sort (skeleton:Skeleton):Void;
|
||||
public abstract function sort(skeleton:Skeleton):Void;
|
||||
|
||||
public function isSourceActive ():Bool {
|
||||
public function isSourceActive():Bool {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -33,11 +33,10 @@ package spine;
|
||||
abstract class ConstraintData< //
|
||||
T:Constraint<Dynamic, Dynamic, Dynamic>, //
|
||||
P:Pose<Any>> //
|
||||
extends PosedData<P> {
|
||||
|
||||
extends PosedData<P> {
|
||||
function new(name:String, setup:P) {
|
||||
super(name, setup);
|
||||
}
|
||||
|
||||
public abstract function create (skeleton:Skeleton):T;
|
||||
public abstract function create(skeleton:Skeleton):T;
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -50,7 +50,8 @@ class Event {
|
||||
public var balance = 0.;
|
||||
|
||||
public function new(time:Float, data:EventData) {
|
||||
if (data == null) throw new SpineException("data cannot be null.");
|
||||
if (data == null)
|
||||
throw new SpineException("data cannot be null.");
|
||||
this.time = time;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
|
||||
@ -25,19 +25,23 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
interface HasTextureRegion {
|
||||
/** The name used to find the region. */
|
||||
public var path:String;
|
||||
|
||||
/** Sets the region used to draw the attachment. After setting the region or if the region's properties are changed,
|
||||
* updateRegion() must be called. */
|
||||
public var region:TextureRegion;
|
||||
|
||||
/** The color to tint the attachment. */
|
||||
public var color:Color;
|
||||
|
||||
public var sequence:Sequence;
|
||||
|
||||
/** Updates any values the attachment calculates using the region. Must be called after setting the
|
||||
* region or if the region's properties are changed. */
|
||||
public function updateRegion():Void;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -34,7 +34,6 @@ package spine;
|
||||
*
|
||||
* @see https://esotericsoftware.com/spine-ik-constraints IK constraints in the Spine User Guide */
|
||||
class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstraintPose> {
|
||||
|
||||
/** The 1 or 2 bones that will be modified by this IK constraint. */
|
||||
public final bones:Array<BonePose>;
|
||||
|
||||
@ -43,7 +42,8 @@ class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstrai
|
||||
|
||||
public function new(data:IkConstraintData, skeleton:Skeleton) {
|
||||
super(data, new IkConstraintPose(), new IkConstraintPose());
|
||||
if (skeleton == null) throw new SpineException("skeleton cannot be null.");
|
||||
if (skeleton == null)
|
||||
throw new SpineException("skeleton cannot be null.");
|
||||
|
||||
bones = new Array<BonePose>();
|
||||
for (boneData in data.bones)
|
||||
@ -51,24 +51,27 @@ class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstrai
|
||||
target = skeleton.bones[data.target.index];
|
||||
}
|
||||
|
||||
public function copy (skeleton:Skeleton) {
|
||||
public function copy(skeleton:Skeleton) {
|
||||
var copy = new IkConstraint(data, skeleton);
|
||||
copy.pose.set(pose);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/** Applies the constraint to the constrained bones. */
|
||||
public function update (skeleton:Skeleton, physics:Physics):Void {
|
||||
public function update(skeleton:Skeleton, physics:Physics):Void {
|
||||
var p = applied;
|
||||
if (p.mix == 0) return;
|
||||
if (p.mix == 0)
|
||||
return;
|
||||
var target = target.applied;
|
||||
switch (bones.length) {
|
||||
case 1: apply1(skeleton, bones[0], target.worldX, target.worldY, p.compress, p.stretch, data.uniform, p.mix);
|
||||
case 2: apply2(skeleton, bones[0], bones[1], target.worldX, target.worldY, p.bendDirection, p.stretch, data.uniform, p.softness, p.mix);
|
||||
case 1:
|
||||
apply1(skeleton, bones[0], target.worldX, target.worldY, p.compress, p.stretch, data.uniform, p.mix);
|
||||
case 2:
|
||||
apply2(skeleton, bones[0], bones[1], target.worldX, target.worldY, p.bendDirection, p.stretch, data.uniform, p.softness, p.mix);
|
||||
}
|
||||
}
|
||||
|
||||
public function sort (skeleton:Skeleton) {
|
||||
public function sort(skeleton:Skeleton) {
|
||||
skeleton.sortBone(target);
|
||||
var parent = bones[0].bone;
|
||||
skeleton.sortBone(parent);
|
||||
@ -76,24 +79,25 @@ class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstrai
|
||||
parent.sorted = false;
|
||||
skeleton.sortReset(parent.children);
|
||||
skeleton.constrained(parent);
|
||||
if (bones.length > 1) skeleton.constrained(bones[1].bone);
|
||||
if (bones.length > 1)
|
||||
skeleton.constrained(bones[1].bone);
|
||||
}
|
||||
|
||||
override public function isSourceActive () {
|
||||
override public function isSourceActive() {
|
||||
return target.active;
|
||||
}
|
||||
|
||||
public function set_target (target:Bone):Bone {
|
||||
if (target == null) throw new SpineException("target cannot be null.");
|
||||
public function set_target(target:Bone):Bone {
|
||||
if (target == null)
|
||||
throw new SpineException("target cannot be null.");
|
||||
this.target = target;
|
||||
return target;
|
||||
}
|
||||
|
||||
/** Applies 1 bone IK. The target is specified in the world coordinate system. */
|
||||
static public function apply1(skeleton:Skeleton, bone:BonePose, targetX:Float, targetY:Float, compress:Bool, stretch:Bool,
|
||||
uniform:Bool, mix:Float) {
|
||||
|
||||
if (bone == null) throw new SpineException("bone cannot be null.");
|
||||
static public function apply1(skeleton:Skeleton, bone:BonePose, targetX:Float, targetY:Float, compress:Bool, stretch:Bool, uniform:Bool, mix:Float) {
|
||||
if (bone == null)
|
||||
throw new SpineException("bone cannot be null.");
|
||||
bone.modifyLocal(skeleton);
|
||||
var p = bone.bone.parent.applied;
|
||||
var pa = p.a, pb = p.b, pc = p.c, pd = p.d;
|
||||
@ -127,7 +131,8 @@ class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstrai
|
||||
switchDefault();
|
||||
}
|
||||
rotationIK += MathUtils.atan2Deg(ty, tx);
|
||||
if (bone.scaleX < 0) rotationIK += 180;
|
||||
if (bone.scaleX < 0)
|
||||
rotationIK += 180;
|
||||
if (rotationIK > 180)
|
||||
rotationIK -= 360;
|
||||
else if (rotationIK < -180) //
|
||||
@ -139,13 +144,14 @@ class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstrai
|
||||
tx = targetX - bone.worldX;
|
||||
ty = targetY - bone.worldY;
|
||||
}
|
||||
var b = bone.bone.data.length * bone.scaleX;
|
||||
var b = bone.bone.data.length * bone.scaleX;
|
||||
if (b > 0.0001) {
|
||||
var dd = tx * tx + ty * ty;
|
||||
var dd = tx * tx + ty * ty;
|
||||
if ((compress && dd < b * b) || (stretch && dd > b * b)) {
|
||||
var s = (Math.sqrt(dd) / b - 1) * mix + 1;
|
||||
bone.scaleX *= s;
|
||||
if (uniform) bone.scaleY *= s;
|
||||
if (uniform)
|
||||
bone.scaleY *= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -153,12 +159,14 @@ class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstrai
|
||||
|
||||
/** Applies 2 bone IK. The target is specified in the world coordinate system.
|
||||
* @param child A direct descendant of the parent bone. */
|
||||
static public function apply2(skeleton:Skeleton, parent:BonePose, child:BonePose, targetX:Float, targetY:Float, bendDir:Int,
|
||||
stretch:Bool, uniform:Bool, softness:Float, mix:Float):Void {
|
||||
|
||||
if (parent == null) throw new SpineException("parent cannot be null.");
|
||||
if (child == null) throw new SpineException("child cannot be null.");
|
||||
if (parent.inherit != Inherit.normal || child.inherit != Inherit.normal) return;
|
||||
static public function apply2(skeleton:Skeleton, parent:BonePose, child:BonePose, targetX:Float, targetY:Float, bendDir:Int, stretch:Bool, uniform:Bool,
|
||||
softness:Float, mix:Float):Void {
|
||||
if (parent == null)
|
||||
throw new SpineException("parent cannot be null.");
|
||||
if (child == null)
|
||||
throw new SpineException("child cannot be null.");
|
||||
if (parent.inherit != Inherit.normal || child.inherit != Inherit.normal)
|
||||
return;
|
||||
parent.modifyLocal(skeleton);
|
||||
child.modifyLocal(skeleton);
|
||||
var px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX;
|
||||
@ -232,8 +240,9 @@ class IkConstraint extends Constraint<IkConstraint, IkConstraintData, IkConstrai
|
||||
cos = 1;
|
||||
if (stretch) {
|
||||
a = (Math.sqrt(dd) / (l1 + l2) - 1) * mix + 1;
|
||||
parent.scaleX *= a;
|
||||
if (uniform) parent.scaleY *= a;
|
||||
parent.scaleX *= a;
|
||||
if (uniform)
|
||||
parent.scaleY *= a;
|
||||
}
|
||||
}
|
||||
a2 = Math.acos(cos) * bendDir;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -33,7 +33,6 @@ package spine;
|
||||
*
|
||||
* @see https://esotericsoftware.com/spine-ik-constraints IK constraints in the Spine User Guide */
|
||||
class IkConstraintData extends ConstraintData<IkConstraint, IkConstraintPose> {
|
||||
|
||||
/** The bones that are constrained by this IK constraint. */
|
||||
public final bones:Array<BoneData> = new Array<BoneData>();
|
||||
|
||||
@ -44,17 +43,17 @@ class IkConstraintData extends ConstraintData<IkConstraint, IkConstraintPose> {
|
||||
* on both the X and Y axes. */
|
||||
public var uniform = false;
|
||||
|
||||
|
||||
public function new(name:String) {
|
||||
super(name, new IkConstraintPose());
|
||||
}
|
||||
|
||||
public function create (skeleton:Skeleton):IkConstraint {
|
||||
public function create(skeleton:Skeleton):IkConstraint {
|
||||
return new IkConstraint(this, skeleton);
|
||||
}
|
||||
|
||||
public function set_target (target:BoneData) {
|
||||
if (target == null) throw new SpineException("target cannot be null.");
|
||||
public function set_target(target:BoneData) {
|
||||
if (target == null)
|
||||
throw new SpineException("target cannot be null.");
|
||||
this.target = target;
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -25,13 +25,12 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
/** Stores the current pose for an IK constraint. */
|
||||
class IkConstraintPose implements Pose<IkConstraintPose> {
|
||||
|
||||
/** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */
|
||||
public var bendDirection = 0;
|
||||
|
||||
@ -39,29 +38,27 @@ class IkConstraintPose implements Pose<IkConstraintPose> {
|
||||
public var compress:Bool = false;
|
||||
|
||||
/** When true and the target is out of range, the parent bone is scaled to reach it.
|
||||
*
|
||||
* For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if softness is
|
||||
* > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */
|
||||
*
|
||||
* For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if softness is
|
||||
* > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */
|
||||
public var stretch:Bool = false;
|
||||
|
||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
|
||||
*
|
||||
* For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */
|
||||
*
|
||||
* For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */
|
||||
public var mix = 0.;
|
||||
|
||||
/** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
|
||||
* will not straighten completely until the target is this far out of range. */
|
||||
* will not straighten completely until the target is this far out of range. */
|
||||
public var softness = 0.;
|
||||
|
||||
public function new () {
|
||||
}
|
||||
public function new() {}
|
||||
|
||||
public function set (pose:IkConstraintPose) {
|
||||
public function set(pose:IkConstraintPose) {
|
||||
mix = pose.mix;
|
||||
softness = pose.softness;
|
||||
bendDirection = pose.bendDirection;
|
||||
compress = pose.compress;
|
||||
stretch = pose.stretch;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -63,7 +63,7 @@ class MathUtils {
|
||||
* @param x The x-coordinate.
|
||||
* @return The arc tangent in degrees.
|
||||
*/
|
||||
static public function atan2Deg (y:Float, x:Float):Float {
|
||||
static public function atan2Deg(y:Float, x:Float):Float {
|
||||
return Math.atan2(y, x) * MathUtils.radDeg;
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -56,9 +56,10 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
private final lengths = new Array<Float>();
|
||||
private final segments = new Array<Float>();
|
||||
|
||||
public function new (data:PathConstraintData, skeleton:Skeleton) {
|
||||
public function new(data:PathConstraintData, skeleton:Skeleton) {
|
||||
super(data, new PathConstraintPose(), new PathConstraintPose());
|
||||
if (skeleton == null) throw new SpineException("skeleton cannot be null.");
|
||||
if (skeleton == null)
|
||||
throw new SpineException("skeleton cannot be null.");
|
||||
|
||||
bones = new Array<BonePose>();
|
||||
for (boneData in data.bones)
|
||||
@ -76,18 +77,23 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
/** Applies the constraint to the constrained bones. */
|
||||
public function update(skeleton:Skeleton, physics:Physics):Void {
|
||||
var attachment = slot.applied.attachment;
|
||||
if (!Std.isOfType(attachment, PathAttachment)) return;
|
||||
if (!Std.isOfType(attachment, PathAttachment))
|
||||
return;
|
||||
var pathAttachment = cast(attachment, PathAttachment);
|
||||
|
||||
var p = applied;
|
||||
var mixRotate = p.mixRotate, mixX = p.mixX, mixY = p.mixY;
|
||||
if (mixRotate == 0 && mixX == 0 && mixY == 0) return;
|
||||
if (mixRotate == 0 && mixX == 0 && mixY == 0)
|
||||
return;
|
||||
|
||||
var data = data;
|
||||
var fTangents = data.rotateMode == RotateMode.tangent, fScale = data.rotateMode == RotateMode.chainScale;
|
||||
var boneCount = bones.length, spacesCount = fTangents ? boneCount : boneCount + 1;
|
||||
var fTangents = data.rotateMode == RotateMode.tangent,
|
||||
fScale = data.rotateMode == RotateMode.chainScale;
|
||||
var boneCount = bones.length,
|
||||
spacesCount = fTangents ? boneCount : boneCount + 1;
|
||||
ArrayUtils.resize(spaces, spacesCount, 0);
|
||||
if (fScale) ArrayUtils.resize(lengths, boneCount, 0);
|
||||
if (fScale)
|
||||
ArrayUtils.resize(lengths, boneCount, 0);
|
||||
var spacing = p.spacing;
|
||||
|
||||
var bones = bones;
|
||||
@ -102,7 +108,8 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
lengths[i] = Math.sqrt(x * x + y * y);
|
||||
}
|
||||
}
|
||||
for (i in 1...spacesCount) spaces[i] = spacing;
|
||||
for (i in 1...spacesCount)
|
||||
spaces[i] = spacing;
|
||||
case SpacingMode.proportional:
|
||||
var sum = 0.;
|
||||
var i = 0, n = spacesCount - 1;
|
||||
@ -110,12 +117,14 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
var bone = bones[i];
|
||||
var setupLength:Float = bone.bone.data.length;
|
||||
if (setupLength < PathConstraint.epsilon) {
|
||||
if (fScale) lengths[i] = 0;
|
||||
if (fScale)
|
||||
lengths[i] = 0;
|
||||
spaces[++i] = spacing;
|
||||
} else {
|
||||
var x = setupLength * bone.a, y = setupLength * bone.c;
|
||||
var length = Math.sqrt(x * x + y * y);
|
||||
if (fScale) lengths[i] = length;
|
||||
if (fScale)
|
||||
lengths[i] = length;
|
||||
spaces[++i] = length;
|
||||
sum += length;
|
||||
}
|
||||
@ -132,19 +141,23 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
var bone = bones[i];
|
||||
var setupLength = bone.bone.data.length;
|
||||
if (setupLength < PathConstraint.epsilon) {
|
||||
if (fScale) lengths[i] = 0;
|
||||
if (fScale)
|
||||
lengths[i] = 0;
|
||||
spaces[++i] = spacing;
|
||||
} else {
|
||||
var x = setupLength * bone.a, y = setupLength * bone.c;
|
||||
var length = Math.sqrt(x * x + y * y);
|
||||
if (fScale) lengths[i] = length;
|
||||
if (fScale)
|
||||
lengths[i] = length;
|
||||
spaces[++i] = (lengthSpacing ? Math.max(0, setupLength + spacing) : spacing) * length / setupLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var positions = computeWorldPositions(skeleton, pathAttachment, spacesCount, fTangents);
|
||||
var boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;
|
||||
var boneX = positions[0],
|
||||
boneY = positions[1],
|
||||
offsetRotation = data.offsetRotation;
|
||||
var tip = false;
|
||||
if (offsetRotation == 0)
|
||||
tip = data.rotateMode == RotateMode.chain;
|
||||
@ -209,20 +222,26 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
ArrayUtils.resize(positions, spacesCount * 3 + 2, 0);
|
||||
var out:Array<Float> = positions, world = new Array<Float>();
|
||||
var closed = path.closed;
|
||||
var verticesLength = path.worldVerticesLength, curveCount = Std.int(verticesLength / 6), prevCurve = NONE;
|
||||
var verticesLength = path.worldVerticesLength,
|
||||
curveCount = Std.int(verticesLength / 6),
|
||||
prevCurve = NONE;
|
||||
|
||||
if (!path.constantSpeed) {
|
||||
var lengths = path.lengths;
|
||||
curveCount -= closed ? 1 : 2;
|
||||
var pathLength = lengths[curveCount];
|
||||
|
||||
if (data.positionMode == PositionMode.percent) position *= pathLength;
|
||||
if (data.positionMode == PositionMode.percent)
|
||||
position *= pathLength;
|
||||
|
||||
var multiplier: Float;
|
||||
var multiplier:Float;
|
||||
switch (data.spacingMode) {
|
||||
case SpacingMode.percent: multiplier = pathLength;
|
||||
case SpacingMode.proportional: multiplier = pathLength / spacesCount;
|
||||
default: multiplier = 1;
|
||||
case SpacingMode.percent:
|
||||
multiplier = pathLength;
|
||||
case SpacingMode.proportional:
|
||||
multiplier = pathLength / spacesCount;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
|
||||
ArrayUtils.resize(world, 8, 0);
|
||||
@ -234,7 +253,8 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
|
||||
if (closed) {
|
||||
p %= pathLength;
|
||||
if (p < 0) p += pathLength;
|
||||
if (p < 0)
|
||||
p += pathLength;
|
||||
curve = 0;
|
||||
} else if (p < 0) {
|
||||
if (prevCurve != BEFORE) {
|
||||
@ -276,8 +296,7 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
path.computeWorldVertices(skeleton, slot, curve * 6 + 2, 8, world, 0, 2);
|
||||
}
|
||||
}
|
||||
addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
|
||||
tangents || (i > 0 && space == 0));
|
||||
addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0));
|
||||
i++;
|
||||
o += 3;
|
||||
}
|
||||
@ -341,13 +360,17 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
w += 6;
|
||||
}
|
||||
|
||||
if (data.positionMode == PositionMode.percent) position *= pathLength;
|
||||
if (data.positionMode == PositionMode.percent)
|
||||
position *= pathLength;
|
||||
|
||||
var multiplier:Float;
|
||||
switch (data.spacingMode) {
|
||||
case SpacingMode.percent: multiplier = pathLength;
|
||||
case SpacingMode.proportional: multiplier = pathLength / spacesCount;
|
||||
default: multiplier = 1;
|
||||
case SpacingMode.percent:
|
||||
multiplier = pathLength;
|
||||
case SpacingMode.proportional:
|
||||
multiplier = pathLength / spacesCount;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
|
||||
var segments = segments;
|
||||
@ -360,7 +383,8 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
|
||||
if (closed) {
|
||||
p %= pathLength;
|
||||
if (p < 0) p += pathLength;
|
||||
if (p < 0)
|
||||
p += pathLength;
|
||||
curve = 0;
|
||||
segment = 0;
|
||||
} else if (p < 0) {
|
||||
@ -509,10 +533,11 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
}
|
||||
}
|
||||
|
||||
public function sort (skeleton:Skeleton) {
|
||||
public function sort(skeleton:Skeleton) {
|
||||
var slotIndex = slot.data.index;
|
||||
var slotBone = slot.bone;
|
||||
if (skeleton.skin != null) sortPathSlot(skeleton, skeleton.skin, slotIndex, slotBone);
|
||||
if (skeleton.skin != null)
|
||||
sortPathSlot(skeleton, skeleton.skin, slotIndex, slotBone);
|
||||
if (skeleton.data.defaultSkin != null && skeleton.data.defaultSkin != skeleton.skin)
|
||||
sortPathSlot(skeleton, skeleton.data.defaultSkin, slotIndex, slotBone);
|
||||
sortPath(skeleton, slot.pose.attachment, slotBone);
|
||||
@ -529,15 +554,17 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
bones[i].bone.sorted = true;
|
||||
}
|
||||
|
||||
public function sortPathSlot (skeleton:Skeleton, skin:Skin, slotIndex:Int, slotBone:Bone) {
|
||||
public function sortPathSlot(skeleton:Skeleton, skin:Skin, slotIndex:Int, slotBone:Bone) {
|
||||
var entries = skin.getAttachments();
|
||||
for (entry in entries) {
|
||||
if (entry.slotIndex == slotIndex) sortPath(skeleton, entry.attachment, slotBone);
|
||||
if (entry.slotIndex == slotIndex)
|
||||
sortPath(skeleton, entry.attachment, slotBone);
|
||||
}
|
||||
}
|
||||
|
||||
private function sortPath (skeleton:Skeleton, attachment:Attachment, slotBone:Bone) {
|
||||
if (!(Std.isOfType(attachment, PathAttachment))) return;
|
||||
private function sortPath(skeleton:Skeleton, attachment:Attachment, slotBone:Bone) {
|
||||
if (!(Std.isOfType(attachment, PathAttachment)))
|
||||
return;
|
||||
var pathBones = cast(attachment, PathAttachment).bones;
|
||||
if (pathBones == null)
|
||||
skeleton.sortBone(slotBone);
|
||||
@ -553,7 +580,7 @@ class PathConstraint extends Constraint<PathConstraint, PathConstraintData, Path
|
||||
}
|
||||
}
|
||||
|
||||
override public function isSourceActive (): Bool {
|
||||
override public function isSourceActive():Bool {
|
||||
return slot.bone.active;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -51,34 +51,38 @@ class PathConstraintData extends ConstraintData<PathConstraint, PathConstraintPo
|
||||
/** An offset added to the constrained bone rotation. */
|
||||
public var offsetRotation:Float = 0;
|
||||
|
||||
public function new (name:String) {
|
||||
public function new(name:String) {
|
||||
super(name, new PathConstraintPose());
|
||||
}
|
||||
|
||||
public function create (skeleton:Skeleton) {
|
||||
public function create(skeleton:Skeleton) {
|
||||
return new PathConstraint(this, skeleton);
|
||||
}
|
||||
|
||||
public function set_slot (slot:SlotData):SlotData {
|
||||
if (slot == null) throw new SpineException("slot cannot be null.");
|
||||
public function set_slot(slot:SlotData):SlotData {
|
||||
if (slot == null)
|
||||
throw new SpineException("slot cannot be null.");
|
||||
this.slot = slot;
|
||||
return slot;
|
||||
}
|
||||
|
||||
public function set_positionMode (positionMode:PositionMode):PositionMode {
|
||||
if (positionMode == null) throw new SpineException("positionMode cannot be null.");
|
||||
public function set_positionMode(positionMode:PositionMode):PositionMode {
|
||||
if (positionMode == null)
|
||||
throw new SpineException("positionMode cannot be null.");
|
||||
this.positionMode = positionMode;
|
||||
return positionMode;
|
||||
}
|
||||
|
||||
public function set_spacingMode (spacingMode:SpacingMode):SpacingMode {
|
||||
if (spacingMode == null) throw new SpineException("spacingMode cannot be null.");
|
||||
public function set_spacingMode(spacingMode:SpacingMode):SpacingMode {
|
||||
if (spacingMode == null)
|
||||
throw new SpineException("spacingMode cannot be null.");
|
||||
this.spacingMode = spacingMode;
|
||||
return spacingMode;
|
||||
}
|
||||
|
||||
public function set_rotateMode (rotateMode:RotateMode):RotateMode {
|
||||
if (rotateMode == null) throw new SpineException("rotateMode cannot be null.");
|
||||
public function set_rotateMode(rotateMode:RotateMode):RotateMode {
|
||||
if (rotateMode == null)
|
||||
throw new SpineException("rotateMode cannot be null.");
|
||||
this.rotateMode = rotateMode;
|
||||
return rotateMode;
|
||||
}
|
||||
|
||||
@ -25,12 +25,11 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
class PathConstraintPose implements Pose<PathConstraintPose> {
|
||||
|
||||
/** The position along the path. */
|
||||
public var position = 0.;
|
||||
|
||||
@ -46,8 +45,7 @@ class PathConstraintPose implements Pose<PathConstraintPose> {
|
||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */
|
||||
public var mixY = 0.;
|
||||
|
||||
public function new () {
|
||||
}
|
||||
public function new() {}
|
||||
|
||||
public function set(pose:PathConstraintPose) {
|
||||
position = pose.position;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -33,10 +33,13 @@ package spine;
|
||||
class Physics {
|
||||
/** Physics are not updated or applied. */
|
||||
public static var none(default, never):Physics = new Physics("none");
|
||||
|
||||
/** Physics are reset to the current pose. */
|
||||
public static var reset(default, never):Physics = new Physics("reset");
|
||||
|
||||
/** Physics are updated and the pose from physics is applied. */
|
||||
public static var update(default, never):Physics = new Physics("update");
|
||||
|
||||
/** Physics are not updated but the pose from physics is applied. */
|
||||
public static var pose(default, never):Physics = new Physics("pose");
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -35,7 +35,6 @@ package spine;
|
||||
* @see https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide
|
||||
*/
|
||||
class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintData, PhysicsConstraintPose> {
|
||||
|
||||
/** The bone constrained by this physics constraint. */
|
||||
public var bone:BonePose = null;
|
||||
|
||||
@ -62,9 +61,10 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
public var remaining = 0.;
|
||||
public var lastTime = 0.;
|
||||
|
||||
public function new(data: PhysicsConstraintData, skeleton: Skeleton) {
|
||||
public function new(data:PhysicsConstraintData, skeleton:Skeleton) {
|
||||
super(data, new PhysicsConstraintPose(), new PhysicsConstraintPose());
|
||||
if (skeleton == null) throw new SpineException("skeleton cannot be null.");
|
||||
if (skeleton == null)
|
||||
throw new SpineException("skeleton cannot be null.");
|
||||
|
||||
bone = skeleton.bones[data.bone.index].constrained;
|
||||
}
|
||||
@ -75,7 +75,7 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
return copy;
|
||||
}
|
||||
|
||||
public function reset (skeleton:Skeleton) {
|
||||
public function reset(skeleton:Skeleton) {
|
||||
remaining = 0;
|
||||
lastTime = skeleton.time;
|
||||
_reset = true;
|
||||
@ -95,7 +95,7 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
|
||||
/** Translates the physics constraint so next update(Physics) forces are applied as if the bone moved an additional
|
||||
* amount in world space. */
|
||||
public function translate (x:Float, y:Float):Void {
|
||||
public function translate(x:Float, y:Float):Void {
|
||||
ux -= x;
|
||||
uy -= y;
|
||||
cx -= x;
|
||||
@ -104,8 +104,10 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
|
||||
/** Rotates the physics constraint so next update(Physics) forces are applied as if the bone rotated around the
|
||||
* specified point in world space. */
|
||||
public function rotate (x:Float, y:Float, degrees:Float):Void {
|
||||
var r = degrees * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);
|
||||
public function rotate(x:Float, y:Float, degrees:Float):Void {
|
||||
var r = degrees * MathUtils.degRad,
|
||||
cos = Math.cos(r),
|
||||
sin = Math.sin(r);
|
||||
var dx = cx - x, dy = cy - y;
|
||||
translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy);
|
||||
}
|
||||
@ -114,16 +116,21 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
public function update(skeleton:Skeleton, physics:Physics):Void {
|
||||
var p = applied;
|
||||
var mix = p.mix;
|
||||
if (mix == 0) return;
|
||||
if (mix == 0)
|
||||
return;
|
||||
|
||||
var x = data.x > 0, y = data.y > 0, rotateOrShearX = data.rotate > 0 || data.shearX > 0, scaleX = data.scaleX > 0;
|
||||
var x = data.x > 0,
|
||||
y = data.y > 0,
|
||||
rotateOrShearX = data.rotate > 0 || data.shearX > 0,
|
||||
scaleX = data.scaleX > 0;
|
||||
var l = bone.bone.data.length, t = data.step, z = 0.;
|
||||
|
||||
switch (physics) {
|
||||
case Physics.none:
|
||||
return;
|
||||
case Physics.reset, Physics.update:
|
||||
if (physics == Physics.reset) reset(skeleton);
|
||||
if (physics == Physics.reset)
|
||||
reset(skeleton);
|
||||
|
||||
var delta = Math.max(skeleton.time - lastTime, 0), aa = remaining;
|
||||
remaining += delta;
|
||||
@ -135,8 +142,8 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
ux = bx;
|
||||
uy = by;
|
||||
} else {
|
||||
var a = remaining, i = p.inertia, f = skeleton.data.referenceScale, d = -1., m = 0., e = 0., ax = 0., ay = 0.,
|
||||
qx = data.limit * delta, qy = qx * Math.abs(skeleton.scaleY);
|
||||
var a = remaining, i = p.inertia, f = skeleton.data.referenceScale, d = -1., m = 0., e = 0., ax = 0., ay = 0., qx = data.limit * delta,
|
||||
qy = qx * Math.abs(skeleton.scaleY);
|
||||
qx *= Math.abs(skeleton.scaleX);
|
||||
if (x || y) {
|
||||
if (x) {
|
||||
@ -174,8 +181,10 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
yLag = yOffset - ys;
|
||||
}
|
||||
z = Math.max(0, 1 - a / t);
|
||||
if (x) bone.worldX += (xOffset - xLag * z) * mix * data.x;
|
||||
if (y) bone.worldY += (yOffset - yLag * z) * mix * data.y;
|
||||
if (x)
|
||||
bone.worldX += (xOffset - xLag * z) * mix * data.x;
|
||||
if (y)
|
||||
bone.worldY += (yOffset - yLag * z) * mix * data.y;
|
||||
}
|
||||
if (rotateOrShearX || scaleX) {
|
||||
var ca = Math.atan2(bone.c, bone.a), c = 0., s = 0., mr = 0., dx = cx - bone.worldX, dy = cy - bone.worldY;
|
||||
@ -198,20 +207,23 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
s = Math.sin(r);
|
||||
if (scaleX) {
|
||||
r = l * bone.worldScaleX;
|
||||
if (r > 0) scaleOffset += (dx * c + dy * s) * i / r;
|
||||
if (r > 0)
|
||||
scaleOffset += (dx * c + dy * s) * i / r;
|
||||
}
|
||||
} else {
|
||||
c = Math.cos(ca);
|
||||
s = Math.sin(ca);
|
||||
var r = l * bone.worldScaleX - scaleLag * Math.max(0, 1 - aa / t);
|
||||
if (r > 0) scaleOffset += (dx * c + dy * s) * i / r;
|
||||
if (r > 0)
|
||||
scaleOffset += (dx * c + dy * s) * i / r;
|
||||
}
|
||||
if (a >= t) {
|
||||
if (d == -1) {
|
||||
d = Math.pow(p.damping, 60 * t);
|
||||
m = t * p.massInverse;
|
||||
e = p.strength;
|
||||
var w = f * p.wind, g = f * p.gravity * Bone.yDir;
|
||||
var w = f * p.wind,
|
||||
g = f * p.gravity * Bone.yDir;
|
||||
ax = (w * skeleton.windX + g * skeleton.gravityX) * skeleton.scaleX;
|
||||
ay = (w * skeleton.windY + g * skeleton.gravityY) * skeleton.scaleY;
|
||||
}
|
||||
@ -227,7 +239,8 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
rotateVelocity -= ((ax * s + ay * c) * h + rotateOffset * e) * m;
|
||||
rotateOffset += rotateVelocity * t;
|
||||
rotateVelocity *= d;
|
||||
if (a < t) break;
|
||||
if (a < t)
|
||||
break;
|
||||
var r:Float = rotateOffset * mr + ca;
|
||||
c = Math.cos(r);
|
||||
s = Math.sin(r);
|
||||
@ -245,8 +258,10 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
cy = bone.worldY;
|
||||
case Physics.pose:
|
||||
z = Math.max(0, 1 - remaining / t);
|
||||
if (x) bone.worldX += (xOffset - xLag * z) * mix * data.x;
|
||||
if (y) bone.worldY += (yOffset - yLag * z) * mix * data.y;
|
||||
if (x)
|
||||
bone.worldX += (xOffset - xLag * z) * mix * data.x;
|
||||
if (y)
|
||||
bone.worldY += (yOffset - yLag * z) * mix * data.y;
|
||||
}
|
||||
|
||||
if (rotateOrShearX) {
|
||||
@ -291,7 +306,7 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
bone.modifyWorld(skeleton._update);
|
||||
}
|
||||
|
||||
public function sort (skeleton: Skeleton) {
|
||||
public function sort(skeleton:Skeleton) {
|
||||
var bone = bone.bone;
|
||||
skeleton.sortBone(bone);
|
||||
skeleton._updateCache.push(this);
|
||||
@ -299,7 +314,7 @@ class PhysicsConstraint extends Constraint<PhysicsConstraint, PhysicsConstraintD
|
||||
skeleton.constrained(bone);
|
||||
}
|
||||
|
||||
override public function isSourceActive () {
|
||||
override public function isSourceActive() {
|
||||
return bone.bone.active;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
@ -33,7 +33,6 @@ package spine;
|
||||
*
|
||||
* @see https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide */
|
||||
class PhysicsConstraintData extends ConstraintData<PhysicsConstraint, PhysicsConstraintPose> {
|
||||
|
||||
/** The bone constrained by this physics constraint. */
|
||||
public var bone:BoneData;
|
||||
|
||||
@ -44,8 +43,10 @@ class PhysicsConstraintData extends ConstraintData<PhysicsConstraint, PhysicsCon
|
||||
public var shearX = 0.;
|
||||
public var limit = 0.;
|
||||
public var step = 0.;
|
||||
|
||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */
|
||||
public var mix = 0.;
|
||||
|
||||
public var inertiaGlobal = false;
|
||||
public var strengthGlobal = false;
|
||||
public var dampingGlobal = false;
|
||||
@ -58,8 +59,7 @@ class PhysicsConstraintData extends ConstraintData<PhysicsConstraint, PhysicsCon
|
||||
super(name, new PhysicsConstraintPose());
|
||||
}
|
||||
|
||||
public function create (skeleton:Skeleton) {
|
||||
public function create(skeleton:Skeleton) {
|
||||
return new PhysicsConstraint(this, skeleton);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,26 +25,25 @@
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
package spine;
|
||||
|
||||
/** Stores a pose for a physics constraint. */
|
||||
class PhysicsConstraintPose implements Pose<PhysicsConstraintPose> {
|
||||
|
||||
public var inertia = 0.;
|
||||
public var strength = 0.;
|
||||
public var damping = 0.;
|
||||
public var massInverse = 0.;
|
||||
public var wind = 0.;
|
||||
public var gravity = 0.;
|
||||
|
||||
/** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */
|
||||
public var mix = 0.;
|
||||
|
||||
public function new () {
|
||||
}
|
||||
public function new() {}
|
||||
|
||||
public function set (pose:PhysicsConstraintPose) {
|
||||
public function set(pose:PhysicsConstraintPose) {
|
||||
inertia = pose.inertia;
|
||||
strength = pose.strength;
|
||||
damping = pose.damping;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user