Skip to content

Commit

Permalink
Rewrite CharacterRegistry and first draft of automatic offset flipping.
Browse files Browse the repository at this point in the history
  • Loading branch information
EliteMasterEric committed Sep 21, 2024
1 parent a41d303 commit 36511fa
Show file tree
Hide file tree
Showing 28 changed files with 509 additions and 315 deletions.
2 changes: 1 addition & 1 deletion assets
7 changes: 3 additions & 4 deletions source/funkin/InitState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry;
import funkin.data.dialogue.speaker.SpeakerRegistry;
import funkin.data.freeplay.album.AlbumRegistry;
import funkin.data.song.SongRegistry;
import funkin.play.character.CharacterData.CharacterDataParser;
import funkin.data.character.CharacterRegistry;
import funkin.play.notes.notekind.NoteKindManager;
import funkin.modding.module.ModuleHandler;
import funkin.ui.title.TitleState;
Expand Down Expand Up @@ -175,9 +175,8 @@ class InitState extends FlxState
AlbumRegistry.instance.loadEntries();
StageRegistry.instance.loadEntries();

// TODO: CharacterDataParser doesn't use json2object, so it's way slower than the other parsers and more prone to syntax errors.
// Move it to use a BaseRegistry.
CharacterDataParser.loadCharacterCache();
// TODO: CharacterRegistry doesn't use json2object, so it's way slower than the other parsers and more prone to syntax errors.
CharacterRegistry.loadCharacterCache();

NoteKindManager.loadScripts();

Expand Down
19 changes: 19 additions & 0 deletions source/funkin/data/character/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Character Data Schema Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0]
### Changed
- Character offsets are now automatically flipped horizontally when the character is flipped.
- This makes the character look correct when reused between player and opponent, but is a breaking change.
- Automatic migration is implemented, so characters using version `1.0.1` won't break.

## [1.0.1]
### Added
- `death.cameraOffsets` to specify the camera position during the death animation.

## [1.0.0]
Initial release.
258 changes: 258 additions & 0 deletions source/funkin/data/character/CharacterData.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
package funkin.data.character;

import funkin.data.animation.AnimationData;
import funkin.modding.events.ScriptEvent;
import funkin.modding.events.ScriptEventDispatcher;
import funkin.play.character.ScriptedCharacter.ScriptedAnimateAtlasCharacter;
import funkin.play.character.ScriptedCharacter.ScriptedBaseCharacter;
import funkin.play.character.ScriptedCharacter.ScriptedMultiSparrowCharacter;
import funkin.play.character.ScriptedCharacter.ScriptedPackerCharacter;
import funkin.play.character.ScriptedCharacter.ScriptedSparrowCharacter;
import funkin.util.assets.DataAssets;
import funkin.util.VersionUtil;
import haxe.Json;
import openfl.utils.Assets;
import flixel.graphics.frames.FlxFrame;

/**
* Describes the available rendering types for a character.
*/
enum abstract CharacterRenderType(String) from String to String
{
/**
* Renders the character using a single spritesheet and XML data.
*/
public var Sparrow = 'sparrow';

/**
* Renders the character using a single spritesheet and TXT data.
*/
public var Packer = 'packer';

/**
* Renders the character using multiple spritesheets and XML data.
*/
public var MultiSparrow = 'multisparrow';

/**
* Renders the character using a spritesheet of symbols and JSON data.
*/
public var AnimateAtlas = 'animateatlas';

/**
* Renders the character using a custom method.
*/
public var Custom = 'custom';
}

/**
* The JSON data schema used to define a character.
*/
typedef CharacterData =
{
/**
* The sematic version number of the character data JSON format.
*/
var version:String;

/**
* The readable name of the character. Used in places like the Chart Editor.
*/
var name:String;

/**
* The type of rendering system to use for the character.
* Supports `sparrow`, `packer`, `multisparrow`, `animateatlas`, and `custom`
* @default `sparrow`
*/
@:optional
@:default("sparrow")
var renderType:CharacterRenderType;

/**
* Behavior varies by render type:
* - `SPARROW`: Path to retrieve both the spritesheet and the XML data from.
* - `PACKER`: Path to retrieve both the spritsheet and the TXT data from.
*/
var assetPath:String;

/**
* The scale of the graphic as a float.
* Pro tip: On pixel-art levels, save the sprites small and set this value to 6 or so to save memory.
* @default `1`
*/
@:optional
@:default(1)
var scale:Null<Float>;

/**
* Optional data about the health icon for the character.
*/
@:optional
var healthIcon:Null<HealthIconData>;

/**
* Optional data about the character's death animation.
*/
@:optional
var death:Null<DeathData>;

/**
* The global offset to the character's position, in pixels.
* @default `[0, 0]`
*/
@:optional
@:default([0, 0])
var offsets:Null<Array<Float>>;

/**
* If `true`, apply additional math to automatically flip a character's offsets for you when the character is flipped.
* If `false`, don't apply any extra math.
*
* NOTE: If you are changing this from `false` to `true` and your character has `flipX` enabled,
* your animation offsets are for the flipped character and you have to invert them horizontally.
*/
@:optional
@:default(true)
var flipXOffsets:Bool;

/**
* If `true`, the character will swap its `singRIGHT` and `singLEFT` animations when the character is flipped.
* If `false`, leave animations as they are.
*/
@:optional
@:default(true)
var flipSingAnimations:Bool;

/**
* The amount to offset the camera by while focusing on this character.
* Default value focuses on the character directly.
* @default `[0, 0]`
*/
@:optional
@:default([0, 0])
var cameraOffsets:Array<Float>;

/**
* Setting this to true disables anti-aliasing for the character.
* @default `false`
*/
@:optional
@:default(false)
var isPixel:Null<Bool>;

/**
* The frequency at which the character will play its idle animation, in beats.
* Increasing this number will make the character dance less often.
* Supports up to `0.25` precision.
* @default `1.0` on characters
*/
@:optional
@:default(1.0)
var danceEvery:Null<Float>;

/**
* The minimum duration that a character will play a note animation for, in beats.
* If this number is too low, you may see the character start playing the idle animation between notes.
* If this number is too high, you may see the the character play the sing animation for too long after the notes are gone.
*
* Examples:
* - Daddy Dearest uses a value of `1.525`.
* @default `1.0`
*/
@:optional
@:default(1.0)
var singTime:Null<Float>;

/**
* An optional array of animations which the character can play.
*/
@:optional
@:default([])
var animations:Array<AnimationData>;

/**
* If animations are used, this is the name of the animation to play first.
* @default `idle`
*/
@:optional
@:default("idle")
var startingAnimation:Null<String>;

/**
* Whether or not the whole ass sprite is flipped by default.
* Useful for characters that could also be played (Pico)
*
* @default `false`
*/
@:optional
@:default(false)
var flipX:Null<Bool>;
};

/**
* The JSON data schema used to define the health icon for a character.
*/
typedef HealthIconData =
{
/**
* The ID to use for the health icon.
* @default The character's ID
*/
@:optional
var id:Null<String>;

/**
* The scale of the health icon.
*/
@:optional
@:default(1.0)
var scale:Null<Float>;

/**
* Whether to flip the health icon horizontally.
* @default `false`
*/
@:optional
@:default(false)
var flipX:Null<Bool>;

/**
* Multiply scale by 6 and disable antialiasing
* @default `false`
*/
@:optional
@:default(false)
var isPixel:Null<Bool>;

/**
* The offset of the health icon, in pixels.
* @default `[0, 25]`
*/
@:optional
@:default([0, 25])
var offsets:Null<Array<Float>>;
}

typedef DeathData =
{
/**
* The amount to offset the camera by while focusing on this character as they die.
* Default value focuses on the character's graphic midpoint.
* @default `[0, 0]`
*/
var ?cameraOffsets:Array<Float>;

/**
* The amount to zoom the camera by while focusing on this character as they die.
* Value is a multiplier of the default camera zoom for the stage.
* @default `1.0`
*/
var ?cameraZoom:Float;

/**
* Impose a delay between when the character reaches `0` health and when the death animation plays.
* @default `0.0`
*/
var ?preTransitionDelay:Float;
}
Loading

0 comments on commit 36511fa

Please sign in to comment.